Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/agent/risk-classifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ const BASH_HIGH: readonly string[] = [
'curl -F',
'wget --post-data',
'wget --post-file',
'launchctl load',
'launchctl bootstrap',
'launchctl submit',
'launchctl start',
'systemctl enable',
'systemctl start',
'systemctl daemon-reload',
];

/**
Expand Down
14 changes: 14 additions & 0 deletions src/agent/safe-destruct-patterns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,18 @@ export const DESTRUCTIVE_PATTERNS: readonly DestructivePattern[] = [
blockReason:
'safe-destruct: blocked [terraform-destroy] — tears down live external infrastructure irrecoverably (new apply creates new resources, not the same ones); run "terraform plan -destroy" to preview. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.',
},
{
id: 'launchctl-service-register',
re: /\blaunchctl\s+(load|bootstrap|submit|start)\b/i,
tier: 'block',
blockReason:
'safe-destruct: blocked [launchctl-service-register] — installs a persistent launchd service that survives reboots and session boundaries; use `afk service install` via /service-setup instead. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.',
},
{
id: 'systemctl-service-enable',
re: /\bsystemctl\s+(enable|start|daemon-reload)\b/i,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Handle systemctl global options before the subcommand

The command form used by this repository is systemctl --user daemon-reload / systemctl --user enable --now (src/service/systemd/install.ts), but this regex requires the subcommand to immediately follow systemctl. I checked systemctl --help, which documents --user as the global option that connects to the user service manager; consequently, the valid persistent registration command systemctl --user enable --now attacker.service produces no safe-destruct match, and the identical literals in BASH_HIGH classify it only as medium. Account for global options before matching the blocked subcommands.

Useful? React with 👍 / 👎.

tier: 'block',
blockReason:
'safe-destruct: blocked [systemctl-service-enable] — enables/starts a systemd unit that persists across sessions and reboots; use `afk service install` via /service-setup instead. This hook cannot be self-bypassed: if the destruction is genuinely intended, stop and ask the operator to run it.',
},
];
7 changes: 7 additions & 0 deletions src/agent/tools/handlers/write-denylist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ export const BUILTIN_WRITE_DENYLIST: readonly string[] = [
// S4: npm publish tokens and Docker registry credentials.
`${homedir()}/.npmrc`,
`${homedir()}/.docker/config.json`,
// S4: LaunchAgent/LaunchDaemon plist dirs — service registration without approval.
`${homedir()}/Library/LaunchAgents`,
`${homedir()}/Library/LaunchDaemons`,
'/Library/LaunchAgents',
'/Library/LaunchDaemons',
// S4: systemd unit dirs — service registration without approval.
`${homedir()}/.config/systemd`,
// S4-win32: Windows credential/config trees. Gated on both process.platform
// and the env var: on POSIX, USERPROFILE/APPDATA may be set in CI/Docker
// but the backslash paths would resolve incorrectly — the platform guard
Expand Down
7 changes: 6 additions & 1 deletion src/agent/tools/hooks/bash-restriction-hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ const INTERPRETER_DENYLIST =
* {@link scrubAllowlistedRefs}, so it needs no exception here.
*/
export const SENSITIVE_PATH_SIGNAL =
/\.ssh\b|\bid_rsa\b|\bid_ed25519\b|\.gnupg\b|\.aws\b|\.config\/gh\b|\.config\/gcloud\b|\.netrc\b|\.password-store\b|\.afk\/config\b|\.npmrc\b|\.docker\/config\.json\b|\.git-credentials\b|\.kube\/config\b|Library\/Application Support\b|\/etc\/shadow\b|\/etc\/sudoers\b|master\.passwd\b/i;
/\.ssh\b|\bid_rsa\b|\bid_ed25519\b|\.gnupg\b|\.aws\b|\.config\/gh\b|\.config\/gcloud\b|\.netrc\b|\.password-store\b|\.afk\/config\b|\.npmrc\b|\.docker\/config\.json\b|\.git-credentials\b|\.kube\/config\b|Library\/Application Support\b|\/etc\/shadow\b|\/etc\/sudoers\b|master\.passwd\b|Library\/LaunchAgents\b|Library\/LaunchDaemons\b|\.config\/systemd\b/i;

export interface BashRestrictionHookOptions {
/**
Expand Down Expand Up @@ -483,6 +483,11 @@ export function builtinBashSensitiveRoots(): readonly string[] {
path.join(home, 'Library', 'Application Support'),
path.join(home, '.password-store'),
path.join(home, '.config', 'gh'),
path.join(home, 'Library', 'LaunchAgents'),
path.join(home, 'Library', 'LaunchDaemons'),
'/Library/LaunchAgents',
'/Library/LaunchDaemons',
path.join(home, '.config', 'systemd', 'user'),
...BUILTIN_READ_DENYLIST,
]);
}
Expand Down
Loading