Skip to content

Discover Augment Code (Auggie CLI + VS Code + JetBrains) — WEB-4950#213

Merged
thatcatfromspace merged 10 commits into
stagingfrom
web-4950-augment-discovery
Jun 26, 2026
Merged

Discover Augment Code (Auggie CLI + VS Code + JetBrains) — WEB-4950#213
thatcatfromspace merged 10 commits into
stagingfrom
web-4950-augment-discovery

Conversation

@thatcatfromspace

@thatcatfromspace thatcatfromspace commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Augment Code to the discovery scanner as a single cross-surface detector (mirroring the GitHub Copilot pattern) that emits a per-surface row for each of Auggie CLI, Augment (VS Code), and Augment (<JetBrains IDE>) — all three share one ~/.augment config, which is attached to a single canonical surface so it is never duplicated across rows. Discovery half of WEB-4950 (the hooks half shipped separately in setup#184).

Footprint detected (verified against a live 0.30.0 install)

  • Detectionauggie binary on PATH (auggie --version); VS Code ext augment.vscode-augment (+ -nightly); JetBrains plugin (id 24072, name contains "Augment").
  • Settings/permissionstoolPermissions → allow/deny/ask (with shellInputRegex retained), hooks preserved verbatim in raw_settings; user + managed scopes (~/.augment/settings.json, /etc/augment/settings.json, Windows C:\ProgramData\augment).
  • MCPmcpServers top-level and augment.advanced.mcpServers (+ flat form), user + workspace scope.
  • Rules/guidelines.augment-guidelines, .augment/rules/*.{md,mdx}, ~/.augment/rules/, ~/.augment/user-guidelines.md, plus hierarchical AGENTS.md/CLAUDE.md (Augment reads these).
  • Skills/commands~/.augment/skills/<name>/SKILL.md, .augment/commands/*.md.

Changes

  • New scripts/coding_discovery_tools/{macos,linux,windows}/augment/ (detector + settings/MCP/rules/skills extractors; macOS holds logic, Win/Linux are thin OS-seam subclasses) + augment_skills_helpers.py.
  • Wiring: 3 new base classes in coding_tool_base.py; create_augment_detector + 4 extractor factories in coding_tool_factory.py; orchestration (memoized accessors, canonical-surface picker, _process_augment_tool, routing, per-user ownership gate) in ai_tools_discovery.py; linux/__init__.py re-exports.
  • Tests: detector/routing/MCP, settings (incl. hooks-preservation + toolPermissions mapping), rules (incl. .mdx + AGENTS.md/CLAUDE.md + user/project dedup), skills (+linux), over-collection/canonical dedup, cross-user skills attribution, and a discovery-flow fail-safe injection.

Review & validation

  • Multi-pass review (independent elite PR review + security review) → fixed a cross-user user-scope skills attribution leak under root MDM scans (now owner-keyed by file_path), a rules user/project duplication, and an extract-then-silently-drop of project/local settings (settings reduced to user+managed); architect validated the fix set as sound.
  • Live-validated on a real ~/.augment 0.30.0 install: detector found Auggie CLI 0.30.0 + Augment (VS Code) 0.859.7; settings extractor parsed the real toolPermissions ask-rules and preserved all 5 hook events in raw_settings.

Test plan

  • Augment suite green (68 tests across detection/settings/MCP/rules/skills/over-collection)
  • Full suite: 1332 passed (only the 9 pre-existing test_copilot_cli_* binary-gate tests fail, and only on this dev machine because it has a real Homebrew copilot binary — unrelated to this change; zero copilot files touched)
  • Import/wiring smoke after rebasing onto staging

Known follow-ups (non-blocking)

  • JetBrains detector rescans all users per-user-iteration under root (N× work) — inherited parity with the existing Copilot detector; rows dedup correctly. Fixing requires changing shared JetBrains code (out of scope).
  • User-scope skills aren't run through _deduplicate_project_items (pre-existing pattern shared with the Copilot path); parity follow-up if desired.

🤖 Generated with Claude Code


Note

Medium Risk
Runs bounded filesystem walks and reads user settings/permissions on customer machines under root scans; risk is mitigated by mirroring the hardened Copilot CLI pattern, per-user canonical/ownership logic, and broad test coverage rather than changes to auth or backend APIs.

Overview
Adds Augment Code to the coding-tools discovery scanner (WEB-4950), following the same multi-surface pattern as GitHub Copilot CLI: separate inventory rows for Auggie CLI, Augment (VS Code), and Augment (<JetBrains IDE>), all backed by one per-user ~/.augment config.

New macOS detector and MCP, rules, settings, and skills extractors are wired through factories and base classes; Linux and Windows reuse that logic via thin OS-seam subclasses. Orchestration in ai_tools_discovery.py memoizes shared extractions (with an unset sentinel so legitimate empty MCP results do not re-trigger walks), picks a canonical surface per _config_path (CLI > VS Code > JetBrains), attaches MCP/rules/skills/permissions only on that row, routes Augment before the generic JetBrains handler, and applies an ownership gate for root multi-user scans so non-owners do not get phantom rows or cross-user skill leakage.

Settings cover user and managed scopes with toolPermissions and hooks in raw_settings; rules and skills include .augment paths plus compatible .claude/.agents home content where applicable. 68 new tests cover detection, routing, deduplication, and fail-safe behavior in the discovery flow.

Reviewed by Cursor Bugbot for commit 8f2aeb1. Bugbot is set up for automated code reviews on this repo. Configure here.

Greptile Summary

Adds Augment Code to the coding-tool discovery scanner, emitting separate inventory rows for Auggie CLI, Augment (VS Code), and Augment (JetBrains IDEs), all sharing one ~/.augment config directory attached to a single canonical surface per user.

  • New extractors (MCP, rules, settings, skills) under macos/, linux/, and windows/augment/ seams follow the established Copilot CLI pattern: memoized whole-disk walks, bounded depth, symlink guards on dirs and subdirs, user-augment-dir skipping to prevent double-collection as project scope.
  • Orchestration in ai_tools_discovery.py uses a _AUGMENT_CACHE_UNSET sentinel to distinguish "not yet run" from "ran and found nothing," picks one canonical surface per user keyed by _config_path, and gates non-owners with _augment_owned_by_user to suppress phantom rows under root multi-user scans.
  • 68 tests cover routing, canonical dedup, cross-user attribution, MCP nesting/dedup, settings scope, rules/skills walks (incl. symlink guards), and discovery fail-safe behavior.

Confidence Score: 4/5

Safe to merge with the missing observability gap addressed; the core scanning, ownership, and dedup logic is well-tested and sound.

The Augment discovery flow — detection, MCP, rules, settings, and skills extraction — ships with zero flow-specific instrumentation. The shared time_step('process_single_tool') aggregates all tools together, so Augment extraction latency and per-phase success/failure rates cannot be isolated when diagnosing customer-machine failures. Engineering standards require per-flow metrics for every new flow.

scripts/coding_discovery_tools/ai_tools_discovery.py — the memoized accessor methods and the main() processing loop need Augment-specific time_step entries and success/failure counters.

Important Files Changed

Filename Overview
scripts/coding_discovery_tools/ai_tools_discovery.py Core orchestration: adds memoized extractors, per-config canonical surface selection, ownership gate, and Augment routing in process_single_tool. No Augment-specific time_step entries or success/failure metrics added.
scripts/coding_discovery_tools/macos/augment/augment.py Detection logic for Auggie CLI / VS Code / JetBrains surfaces. VS Code de-duplication (stable preferred over nightly) and per-owner JetBrains attribution are correctly implemented.
scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py MCP extraction with JSONC parsing, user-dir guard to prevent double-collection, and workspace walk with symlink/depth guards. Individual settings.json file symlink check noted in existing thread.
scripts/coding_discovery_tools/macos/augment/augment_rules_extractor.py Rules extraction for user-guidelines, .augment/rules/, .augment-guidelines, AGENTS.md/CLAUDE.md with proper symlink guards, user-augment-dir skipping, and bounded depth walk.
scripts/coding_discovery_tools/macos/augment/augment_settings_extractor.py Settings extraction for user and managed scopes; toolPermissions mapped to allow/deny/ask; hooks preserved in raw_settings; oversize file guard and JSONC parsing.
scripts/coding_discovery_tools/macos/augment/augment_skills_extractor.py Skills/commands extraction with symlink guards on both .augment parent dirs and skills/commands subdirs; user-level dir detection prevents double-counting.
scripts/coding_discovery_tools/augment_skills_helpers.py Thin delegation layer connecting Augment's .augment/.claude/.agents parent dirs to the shared ItemTypeConfig engine; clean and correct.
scripts/coding_discovery_tools/linux/augment/augment_rules_extractor.py Linux seam override: per-user error guard added (matching skills extractor), uses linux get_top_level_directories and should_skip_system_path (does not skip /home).
scripts/coding_discovery_tools/linux/augment/augment_settings_extractor.py Linux settings seam: iterates get_linux_user_homes without an outer per-user try/except; safe because extract_for_user already catches Exception, but inconsistent with the guarded pattern in skills/rules extractors.
scripts/coding_discovery_tools/windows/augment/augment.py Windows detector: overrides user-home scan (C:\Users), auggie binary resolution (npm .cmd shim, WinGet, .bun), and JetBrains detector seam.
scripts/coding_discovery_tools/coding_tool_base.py Adds three new abstract base classes (BaseAugmentRulesExtractor, BaseAugmentSettingsExtractor, BaseAugmentSkillsExtractor) to the existing hierarchy.
scripts/coding_discovery_tools/coding_tool_factory.py Registers Augment detector and four extractor factories for macOS/Windows/Linux; imports and OS routing look correct.
tests/test_augment_discovery.py 63 tests covering routing, canonical dedup, cross-user attribution, MCP nesting/dedup, settings scope, and rules/skills walks including symlink guards.
tests/test_augment_overcollection.py Tests that shared config attaches to exactly one canonical surface row and that non-owners are correctly gated under multi-user root scans.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Main as main()
    participant Det as AIToolsDetector
    participant AugDet as MacOSAugmentDetector
    participant MCP as AugmentMCPExtractor
    participant Rules as AugmentRulesExtractor
    participant Sett as AugmentSettingsExtractor
    participant Skills as AugmentSkillsExtractor

    Main->>Det: detect_all_tools()
    Det->>AugDet: detect()
    AugDet-->>Det: [AuggCLI, VSCode, JetBrains] rows (each with _config_path)
    Main->>Det: _set_canonical_augment_surface(tools)
    Note over Det: Groups by _config_path → picks CLI > VSCode > JB per user

    loop for each tool
        Main->>Det: process_single_tool(tool)
        Det->>Det: _process_augment_tool(tool)
        alt canonical surface
            Det->>MCP: extract_mcp_config() [memoized]
            MCP-->>Det: "{projects: [{path, mcpServers}]}"
            Det->>Rules: extract_all_augment_rules() [memoized]
            Rules-->>Det: "[{project_root, rules[]}]"
            Det->>Skills: extract_all_skills() [memoized]
            Skills-->>Det: "{user_skills[], project_skills[]}"
            Det->>Sett: extract_settings() [memoized]
            Sett-->>Det: "[{scope, settings_path, permissions}]"
            Det-->>Main: tool with projects[] + permissions
        else non-canonical surface
            Det-->>Main: "bare row (projects=[])"
        end
        Main->>Main: filter_tool_projects_by_user()
        Main->>Main: _augment_owned_by_user() gate
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Main as main()
    participant Det as AIToolsDetector
    participant AugDet as MacOSAugmentDetector
    participant MCP as AugmentMCPExtractor
    participant Rules as AugmentRulesExtractor
    participant Sett as AugmentSettingsExtractor
    participant Skills as AugmentSkillsExtractor

    Main->>Det: detect_all_tools()
    Det->>AugDet: detect()
    AugDet-->>Det: [AuggCLI, VSCode, JetBrains] rows (each with _config_path)
    Main->>Det: _set_canonical_augment_surface(tools)
    Note over Det: Groups by _config_path → picks CLI > VSCode > JB per user

    loop for each tool
        Main->>Det: process_single_tool(tool)
        Det->>Det: _process_augment_tool(tool)
        alt canonical surface
            Det->>MCP: extract_mcp_config() [memoized]
            MCP-->>Det: "{projects: [{path, mcpServers}]}"
            Det->>Rules: extract_all_augment_rules() [memoized]
            Rules-->>Det: "[{project_root, rules[]}]"
            Det->>Skills: extract_all_skills() [memoized]
            Skills-->>Det: "{user_skills[], project_skills[]}"
            Det->>Sett: extract_settings() [memoized]
            Sett-->>Det: "[{scope, settings_path, permissions}]"
            Det-->>Main: tool with projects[] + permissions
        else non-canonical surface
            Det-->>Main: "bare row (projects=[])"
        end
        Main->>Main: filter_tool_projects_by_user()
        Main->>Main: _augment_owned_by_user() gate
    end
Loading

Reviews (12): Last reviewed commit: "fix(augment): guard symlinked skills/com..." | Re-trigger Greptile

Context used:

  • Context used - P0 — Critical (must block merge)
    Django / Backend ... (source)

thatcatfromspace and others added 2 commits June 25, 2026 15:31
…rains

Add Augment Code (label "augment") to the coding-discovery scanner as a
single cross-surface detector returning per-surface rows (Auggie CLI,
Augment (VS Code), Augment (<JetBrains IDE>)) that share one ~/.augment
config. Mirrors the GitHub Copilot cross-surface pattern.

Extraction parity with claude_code/copilot_cli:
- settings/permissions: toolPermissions -> allow/deny/ask; hooks preserved
  in raw_settings (user/managed/project/local scopes)
- MCP servers: top-level mcpServers + augment.advanced.mcpServers + flat form
- rules/guidelines: .augment-guidelines, .augment/rules/*.{md,mdx},
  ~/.augment/rules, ~/.augment/user-guidelines.md, hierarchical AGENTS.md/CLAUDE.md
- skills/commands: ~/.augment/skills/<name>/SKILL.md, .augment/commands/*.md

Shared ~/.augment config is attached to a single canonical surface
(Auggie CLI > VS Code > JetBrains) to avoid duplication; non-canonical
surfaces emit bare detection rows. macOS holds the logic; Windows/Linux
are thin OS-seam subclasses.

Part of WEB-4950 (discovery half).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…settings scope)

- Owner-key user-scope skills by file_path so a user's skill content can't leak
  onto another user's row under a root all-users scan (mirrors
  _copilot_skill_owner_home)
- Guard the rules project walk against re-collecting ~/.augment/rules as project
  scope, matching the settings/skills extractors' user-dir guards
- Settings: extract user + managed only; drop the unsurfaceable project/local
  filesystem walk; include managed scope in the permissions filter
- Skip symlinked dirs before the .augment branch in the rules walk
- Memo parity for _get_augment_mcp; settings docstring fix
- Add regression tests for the cross-user skills leak and rules duplication

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thatcatfromspace thatcatfromspace requested a review from a team June 25, 2026 10:09
@vigneshsubbiah16

Copy link
Copy Markdown
Contributor

🛡️ Automated Security Review (consensus)

2 findings — 1 high-confidence, 1 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 Privileged scan executes user-writable auggie binaries

scripts/coding_discovery_tools/macos/augment/augment.py:~156–210 (inherited on Linux/Windows via subclass)

Impact: During root/admin all-users MDM scans, the detector resolves auggie from per-user paths (~/.local/bin, ~/.bun/bin, ~/.nvm/..., Windows %APPDATA%\npm\auggie.cmd, etc.) and runs auggie --version as root/SYSTEM — a local user can plant a malicious binary for arbitrary code execution (privilege escalation).

Fix: Do not execute binaries from untrusted (user-owned/writable) paths under a privileged scan; derive version from package metadata (package.json / install manifest) or gate execution on root-owned, non-writable binaries and/or drop privileges to the owning user before invoking.

Flagged by: Claude, Cursor


🟡 MCP config reads lack size cap (memory DoS)

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:~195

Impact: _read_mcp_config calls read_text() with no byte limit on settings.json / mcp*.json, while the settings extractor caps at 1 MB; a planted multi-GB file on a walked path can spike scanner memory during workspace walks (worse under root scans).

Fix: Apply the same stat().st_size guard used in augment_settings_extractor._parse_jsonc before reading MCP config files.

Flagged by: Claude


Previously acknowledged (not re-flagged)

  • JetBrains detector re-scans all users on every per-user iteration under root (N× redundant work) — inherited Copilot parity; fixing requires shared JetBrains changes and is explicitly out of scope for this PR.

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head 14a88f7d · 2026-06-25T10:11Z

Comment thread scripts/coding_discovery_tools/ai_tools_discovery.py Outdated
Comment thread scripts/coding_discovery_tools/windows/augment/augment_skills_extractor.py Outdated
Comment thread scripts/coding_discovery_tools/macos/augment/augment_skills_extractor.py Outdated
Comment thread scripts/coding_discovery_tools/ai_tools_discovery.py
Comment thread scripts/coding_discovery_tools/ai_tools_discovery.py
Comment thread scripts/coding_discovery_tools/macos/augment/augment_skills_extractor.py Outdated
Comment thread scripts/coding_discovery_tools/macos/augment/augment.py Outdated
…ndows

The rules/skills project-walk tests instantiate the macOS extractor and
patched only _iter_top_level_dirs, leaving _filesystem_root at "/". On
Windows the walk's item.relative_to("/") raises ValueError for a C:\ temp
path, so every subdirectory was skipped and project rules/skills were never
collected (8 Windows-only unittest failures, all in the rules/skills suites).
Pin _filesystem_root to the temp ancestor so relative_to works cross-platform.
Production is unaffected: real Windows uses the Windows*AugmentExtractor with
the correct filesystem root.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vigneshsubbiah16

Copy link
Copy Markdown
Contributor

🛡️ Automated Security Review (consensus)

4 findings — 2 high-confidence, 2 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 Privileged scan executes user-writable auggie binaries

scripts/coding_discovery_tools/macos/augment/augment.py:159 (also :204, :49; inherited on Windows/Linux)
Impact: Under root/admin all-users scans, the detector resolves each user's ~/.local/bin/auggie / ~/.bun/bin/auggie / nvm paths and runs auggie --version via run_command — executing a binary writable by that unprivileged user as root (local privesc / arbitrary code execution).
Fix: Do not execute binaries from per-user-writable locations while privileged; skip the version probe under multi-user scans or verify ownership/trust before exec (derive version from package metadata instead).
Flagged by: Claude, Lead

🔴 Managed permissions bypass ownership gate

scripts/coding_discovery_tools/ai_tools_discovery.py:204 (also :1851–1859, :2899–2910)
Impact: _augment_owned_by_user treats retained permissions as has_data; because _process_augment_tool always attaches managed policy and filter_tool_projects_by_user keeps managed permissions for every user, a non-owner with no scoped projects can pass the gate and receive a surface report tied to another user's install_path/_config_path.
Fix: Base has_data only on user/project-scoped signals (ownership of _config_path or non-managed project content); exclude managed-only permissions from the ownership test.
Flagged by: Cursor, Claude

🟡 Windows skills walk omits cross-tool config guard

scripts/coding_discovery_tools/windows/augment/augment_skills_extractor.py:35
Impact: _should_skip_walk_item only skips Windows system dirs, unlike macOS/Linux Augment and Windows Copilot CLI extractors — the whole-disk walk may descend into other tools' config directories and over-collect unrelated skill/command content.
Fix: Add traverses_other_tool_config_dir(item) to _should_skip_walk_item, matching the macOS/Linux Augment and Copilot CLI patterns.
Flagged by: Cursor

🟡 Skills walk follows symlinked .augment directories

scripts/coding_discovery_tools/macos/augment/augment_skills_extractor.py:119–133
Impact: .augment name dispatch runs before the symlink guard (rules/MCP walkers guard first), so a symlinked .augment directory can be traversed and skills extracted from an unintended target path.
Fix: Skip symlinked directories before the .augment branch (not item.is_dir() or item.is_symlink()), matching augment_rules_extractor.py.
Flagged by: Cursor, Greptile

Previously acknowledged (not re-flagged)

  • JetBrains detector rescans all users per-user-iteration under root (N× work) — accepted as inherited Copilot parity; fixing requires shared JetBrains code and is out of scope for this PR.

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head 45eae7b6 · 2026-06-25T10:34Z

Comment thread scripts/coding_discovery_tools/macos/augment/augment.py Outdated
"publisher": "Augment Computer",
"install_path": binary,
"_config_path": str(_resolve_augment_dir(user_home)),
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Root scan runs user auggie

High Severity

During privileged multi-user scans, the detector resolves the auggie CLI binary from user-writable paths (e.g., ~/.local/bin). Running auggie --version on these untrusted binaries can execute arbitrary code with the scanner's elevated privileges.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 45eae7b. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Deferring this as a separate, repo-wide hardening rather than fixing Augment in isolation. The same pattern — resolving a per-user CLI binary from user-writable paths (~/.local/bin, ~/.bun/bin, nvm) and running --version under a root/MDM scan — already ships in the Copilot CLI detector (macos/copilot_cli/copilot_cli.py _detect_for_userget_version) and the Claude binary detector. Hardening only Augment would leave the siblings exposed and diverge the detector family, so this should be one repo-wide change (under root: only exec root-owned, non-world-writable binaries, else report version "unknown"). Will track separately.

Comment thread scripts/coding_discovery_tools/macos/augment/augment.py Outdated
Comment thread scripts/coding_discovery_tools/ai_tools_discovery.py

def _extract_user_configs_for_user(self, user_home: Path) -> List[Dict]:
"""Read the User-scope MCP config(s) for a single user's ``~/.augment``."""
augment_dir = _resolve_augment_dir(user_home)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Agentic Security Review
Severity: HIGH
User-scope Augment extraction trusts ~/.augment as-is and then reads files beneath it without resolving/containing symlinks. In privileged all-users scans, a low-privilege user can symlink their ~/.augment to another user-readable location and cause cross-user MCP/settings/rules/skills ingestion under the wrong identity.
Impact: cross-user data exposure and misattribution during root/admin discovery runs.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit 45eae7b. Configure here.

bucket["mcpServers"] = self._union_mcp_servers(
bucket.get("mcpServers", []), project.get("mcpServers", [])
)
log_mcp_details(projects_dict, tool_name)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Agentic Security Review
Severity: MEDIUM
The new Augment path now emits MCP details via log_mcp_details, which logs full command/arg strings at info level. MCP server args frequently carry tokens/keys (--api-key, bearer values), so this can leak sensitive material into operational logs.
Impact: credential or secret disclosure through log aggregation/retention.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit 45eae7b. Configure here.

thatcatfromspace and others added 2 commits June 25, 2026 17:05
…dedup, symlink, ownership)

Cursor + Greptile inline review follow-ups:

- G: canonical Augment surface is now chosen PER USER (keyed by _config_path),
  not a single global name. A root multi-user scan picks a winner for each
  user's ~/.augment independently, so a VS Code-only user no longer gets a bare
  row that drops their config when another user has the CLI.
- F: managed-scope-only permissions (org-wide /etc/augment) no longer manufacture
  a phantom Augment row for a non-owner under root scans (_augment_owned_by_user
  no longer counts managed permissions as user-owned data).
- B: MCP accessor memoization uses a distinct UNSET sentinel so a legitimate
  cached None (no MCP configured) short-circuits instead of re-running the full
  MCP walk on every surface.
- C: emit at most one "Augment (VS Code)" row per user (prefer stable over
  nightly) so stable+nightly installs don't create duplicate canonical rows.
- A: skills walk skips symlinked dirs before the .augment handling (mirrors the
  rules/mcp/settings walks) so a symlinked .augment can't be followed.
- E: Windows skills walk also skips other-tool config dirs (parity with the
  macOS base + Windows rules walk).

D (Linux rules per-user error guard) was already covered by the macOS base
_extract_user_rules try/except that the Linux subclass inherits.

Adds per-user-canonical, managed-ownership, MCP-memo, dual-extension, and
symlink regression tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ans (H2)

Under a root MDM all-users scan, MacOSJetBrainsDetector returns every user's
IDEs, but the Augment JetBrains row stamped _config_path from the outer scan
home — so an IDE owned by user B could be attributed to user A's ~/.augment
(wrong permissions/config). Run JetBrains detection once and derive each IDE's
owning user from the IDE's own config path (longest-prefix match against the
scanned homes), falling back to the scoped/current home. This also removes the
prior N-times-redundant rescan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vigneshsubbiah16

Copy link
Copy Markdown
Contributor

🛡️ Automated Security Review (consensus)

2 findings — 1 high-confidence, 1 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 HIGH — User-scope ~/.augment reads lack symlink containment

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:108, augment_settings_extractor.py:153, augment_rules_extractor.py (_extract_user_rules)
Impact: Under privileged root/MDM all-users scans, a user can symlink their ~/.augment to another user's config (or any root-readable path); the scanner reads the target and attributes MCP/settings/rules to the wrong identity — cross-user config exposure and misattribution.
Fix: Before reading user-scope config, reject symlinked ~/.augment dirs and verify dir.resolve() stays under the owning user_home (mirror the is_symlink() guards already used in project walks); skip and log on escape.
Flagged by: Cursor (Agentic Security Review), Claude

🟡 TRIAGE — Augment path may log MCP server secrets via log_mcp_details

scripts/coding_discovery_tools/ai_tools_discovery.py:1875
Impact: _process_augment_tool calls log_mcp_details on collected MCP servers; if that helper logs command/args verbatim at info level, tokens/keys in MCP config can land in operational logs.
Fix: Confirm log_mcp_details redacts command/args/env (or logs counts/names only); if not, redact before logging.
Flagged by: Cursor (Agentic Security Review), Claude (unconfirmed — helper is pre-existing, not in this diff)

Previously acknowledged (not re-flagged)

  • Privileged scan executes user-writable auggie binaries (macos/augment/augment.py:214) — @thatcatfromspace deferred as repo-wide hardening (parity with existing Copilot CLI / Claude binary detectors); tracking separately, not Augment-only.
  • Managed-permissions ownership-gate bypass (ai_tools_discovery.py:204) — no longer live in this diff; _augment_owned_by_user excludes managed-scope permissions from the ownership gate (covered by TestAugmentManagedOnlyOwnership).

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head bfe52615 · 2026-06-25T11:57Z

The new H2 regression test hardcoded "/Users/bob/.augment", but production
stringifies a Path, so on Windows _config_path is "\\Users\\bob\\.augment" and
the literal-POSIX assertion failed (Windows CI). Build the expected value via
Path so the separator matches the host OS. Test-only; production is correct.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vigneshsubbiah16

Copy link
Copy Markdown
Contributor

🛡️ Automated Security Review (consensus)

2 findings — 1 high-confidence, 1 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 HIGH — User-scope ~/.augment reads not symlink-contained

macos/augment/augment_mcp_config_extractor.py:95 (same pattern in augment_settings_extractor.py:_extract_user_settings, augment_rules_extractor.py:_extract_user_rules, augment_skills_extractor.py / augment_skills_helpers.py:extract_augment_user_level_items)

Impact: In privileged all-users scans, a low-privilege user can symlink their ~/.augment to another readable location; the scanner follows it and attributes MCP/settings/rules/skills to the wrong _config_path/user identity.

Fix: Before user-scope extraction, reject or contain the config dir — e.g. skip when augment_dir.is_symlink(), or resolve() and verify the result stays under the scanned user_home.

Flagged by: Cursor (Agentic Security Review), Claude


🟡 TRIAGE — MCP server args may leak into operational logs

scripts/coding_discovery_tools/ai_tools_discovery.py:1875 (log_mcp_details in _process_augment_tool)

Impact: The new Augment path logs full MCP server command/arg strings at info level; args often carry API keys or bearer tokens that can land in aggregated/retained logs.

Fix: Redact known secret-bearing flags in log_mcp_details, or log server names/counts only; confirm whether the shared Copilot helper already redacts before treating as accepted.

Flagged by: Cursor (Agentic Security Review), Claude


Previously acknowledged (not re-flagged)

  • Privileged scan executes user-writable auggie binaries (macos/augment/augment.py:214) — @thatcatfromspace: defer as a separate repo-wide hardening (same pattern already ships in Copilot CLI and Claude binary detectors; Augment-only fix would diverge the detector family).

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head d75e5913 · 2026-06-25T12:13Z

"_config_path": str(_resolve_augment_dir(user_home)),
}

def _resolve_binary(self, user_home: Path) -> Optional[str]:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Agentic Security Review
Severity: HIGH
_detect_auggie_cli_for_user() resolves auggie from user-writable home paths and immediately executes it via get_version(binary) during all-users scanning. In privileged discovery runs, this lets a low-privilege local user plant a malicious auggie binary and get execution under the scanner's elevated identity.
Impact: local privilege escalation to the discovery process account (root/admin) and host compromise.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit d75e591. Configure here.

…eptile)

Parity with LinuxAugmentSkillsExtractor: wrap each per-user extract_for_user in
try/except (PermissionError, OSError) so one unreadable home can't abort the
whole multi-user rules scan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vigneshsubbiah16

Copy link
Copy Markdown
Contributor

🛡️ Automated Security Review (consensus)

3 findings — 2 high-confidence, 1 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 HIGH — Symlinked rule/guideline files read without containment

  • Location: scripts/coding_discovery_tools/macos/augment/augment_rules_extractor.py:291
  • Impact: A symlinked .augment/rules/*.md, .augment-guidelines, AGENTS.md, or CLAUDE.md can point outside the project tree; privileged scans follow it and emit arbitrary host file contents to the backend.
  • Fix: Reject symlinked files before read (not item.is_symlink() in _walk_rules_dir; early return in _add_rule_file); optionally resolve() and assert the target stays under the owning project/user root.
  • Flagged by: Cursor, Claude

🔴 HIGH — User-scope ~/.augment tree not symlink-contained

  • Location: scripts/coding_discovery_tools/macos/augment/augment.py:39
  • Impact: Under root/MDM all-users scans, a user can symlink ~/.augment (or settings.json beneath it) to another user's readable config; MCP servers, toolPermissions, rules, and skills are ingested and misattributed under the attacker's identity.
  • Fix: For privileged scans, realpath user-scope config roots and skip when the resolved path escapes the owning home (or owner uid ≠ home owner); apply the same guard in _read_mcp_config / settings parsers that use path.is_file().
  • Flagged by: Cursor, Claude

🟡 TRIAGE — MCP server args may leak into operational logs

  • Location: scripts/coding_discovery_tools/ai_tools_discovery.py:1875
  • Impact: The new Augment path calls log_mcp_details at info level with full command/arg strings; MCP configs often embed API keys or bearer tokens that land in log aggregation/retention.
  • Fix: Redact known secret-bearing flags before logging, or log only server names/counts at info and gate full payloads behind debug (matches hardening worth for other tools).
  • Flagged by: Cursor, Claude

Previously acknowledged (not re-flagged)

  • Privileged execution of user-writable auggie binaries@thatcatfromspace deferred as repo-wide detector-family hardening (Copilot CLI / Claude parity), tracked separately.
  • MCP cache sentinel / empty-result memoization — fixed via _AUGMENT_CACHE_UNSET.
  • VS Code stable+nightly duplicate canonical rows — fixed (prefer stable; emit at most one row).
  • Linux rules extractor missing per-user error guard — fixed per @thatcatfromspace (try/except around each extract_for_user).
  • Managed-only permissions bypassing ownership gate — fixed in _augment_owned_by_user (managed scope alone does not count as user-owned data).
  • Windows skills walk missing traverses_other_tool_config_dir — fixed in WindowsAugmentSkillsExtractor._should_skip_walk_item.
  • JetBrains _config_path misattribution under root scans — fixed via _augment_owner_home_for_path.
  • Symlinked .augment directory followed in skills project walk — fixed (symlink guard before .augment name dispatch).
  • MCP workspace walk double-counting ~/.augment/settings.json — known data-quality defect (Greptile); not a security boundary issue.

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head 747f7bea · 2026-06-25T12:24Z

…ptile)

The MCP workspace walk descended into user homes and re-read
~/.augment/settings.json as PROJECT scope — the same servers already collected
as USER scope — emitting duplicate MCP servers under two project paths
(~/.augment as "user" + the home dir as "project"). Record each user-home
~/.augment collected as user scope and skip it in the workspace walk, matching
the rules/settings/skills user-dir guards. Genuine project .augment dirs are
still collected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vigneshsubbiah16

Copy link
Copy Markdown
Contributor

🛡️ Automated Security Review (consensus)

2 findings — 2 high-confidence, 0 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 HIGH — Symlinked rule/guideline files read without containment

scripts/coding_discovery_tools/macos/augment/augment_rules_extractor.py:288 (also :308)

  • Impact: Project walks skip symlinked directories but _walk_rules_dir / _add_rule_file accept symlinked .md/.mdx (and repo-root guideline files); is_file()/read_text() follow the link, so a planted .augment/rules/x.md/etc/shadow (or another user's home) exfiltrates arbitrary readable file content as rule payload during privileged scans.
  • Fix: Reject symlinks before read — add item.is_symlink() in the file branch of _walk_rules_dir and rule_file.is_symlink() in _add_rule_file; ideally assert resolve() stays under the expected project/.augment root.
  • Reviewers: Cursor, Claude

🔴 HIGH — User-scope ~/.augment not symlink-contained (cross-user ingestion)

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:99 (also augment_settings_extractor.py:147, augment_rules_extractor.py:112)

  • Impact: Per-user extraction trusts <home>/.augment as-is and reads settings.json / MCP files / user rules beneath it without verifying the dir is a real, owner-contained directory; a user can ln -s /Users/B/.augment ~/.augment and cause B's MCP servers, permissions, and rules to be ingested and attributed to A under root/MDM all-users scans.
  • Fix: Before any user-scope read, reject augment_dir.is_symlink() and require augment_dir.resolve() is strictly under user_home.resolve(); skip the user on failure.
  • Reviewers: Cursor, Claude

Previously acknowledged (not re-flagged)

  • Privileged scan executes user-writable auggie binaries@thatcatfromspace deferred to a separate repo-wide hardening (same pattern already ships in Copilot CLI and Claude binary detectors; fixing Augment alone would diverge the family).
  • MCP cache sentinel collision / workspace walk duplicate MCP entries@thatcatfromspace fixed (_AUGMENT_CACHE_UNSET sentinel + skip user-home ~/.augment in workspace walk; regression test added).
  • Linux rules extractor missing per-user error guard@thatcatfromspace fixed (try/except (PermissionError, OSError) per user, parity with skills extractor).
  • log_mcp_details may log MCP command/arg strings (token leakage) — mirrors the existing Copilot call path; not re-flagged as an Augment-specific regression.

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head a6bf47dc · 2026-06-25T12:42Z

return None

mcp_servers_obj = _extract_servers_obj(config_data)
mcp_servers_array = transform_mcp_servers_to_array(mcp_servers_obj)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Agentic Security Review
Severity: HIGH
Workspace .<augment>/settings.json data is treated as trusted enough to invoke transform_mcp_servers_to_array, which actively scans MCP servers and can spawn configured stdio commands. Because this workspace file is attacker-controlled project content, a privileged all-users scan can be coerced into executing arbitrary commands from untrusted config.
Impact: privilege-boundary command execution during discovery (especially under root/admin scans), with potential host compromise or unauthorized outbound actions.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit a6bf47d. Configure here.

…onfig dir

Two follow-ups from dogfooding the Auggie CLI:

1. Auggie loads skills/commands from .augment, .claude AND .agents (per
   docs.augmentcode.com/cli/skills, in both workspace and home) and honors
   .claude/commands for Claude compatibility. The Augment skills extractor now
   sources all three marker dirs (user + project). The same .claude/.agents item
   is reported under Claude Code / Copilot CLI AND Augment by design — each tool
   reports what it loads; the backend dedups per (tool, home_user).

2. Group user-scope skills under their CONFIG DIR (~/.augment, ~/.claude,
   ~/.agents) instead of the bare home. The backend keys an AIToolProject per
   project path, so the old bare-home key surfaced a spurious "~" project
   separate from the ~/.augment rules/MCP project; now ~/.augment skills coalesce
   with that row's rules/MCP, while ~/.claude/~/.agents skills group under their
   own dir. Still owner-scoped (home is in the path) so the per-user filter
   prevents cross-user skill leakage under root scans.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
and Path(str(s["settings_path"])).parent == Path(config_dir)
)
]
permissions_payload = transform_settings_to_backend_format(own) if own else None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

User hooks dropped when managed exists

Medium Severity

_process_augment_tool passes both managed and user settings into transform_settings_to_backend_format, which keeps only the highest-precedence record. When org managed settings.json exists, user hooks in raw_settings are omitted from the payload even though this PR relies on those hooks for risk classification.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5333ad8. Configure here.

Comment thread scripts/coding_discovery_tools/macos/augment/augment_skills_extractor.py Outdated

@vigneshsubbiah16 vigneshsubbiah16 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛡️ Automated Security Review (consensus)

1 finding — 1 high-confidence, 0 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 HIGH — Symlinked rule/config files read without path containment

scripts/coding_discovery_tools/macos/augment/augment_rules_extractor.py:298 (also augment_settings_extractor.py:57, augment_mcp_config_extractor.py:218)
Impact: Project walks skip symlinked directories, but file reads gate only on is_file() (which follows symlinks); under root/MDM scans a planted symlink (e.g. ~/.augment/rules/x.md, AGENTS.md, settings.json) can pull arbitrary host files into the discovery payload.
Fix: Before reading, reject path.is_symlink() and/or verify path.resolve() stays under the intended user/project root; apply uniformly in _add_rule_file, _parse_jsonc, and _read_mcp_config (and the shared skills file-read path).
Reviewers: Claude, Cursor, Lead

Previously acknowledged (not re-flagged)

  • Privileged scan executes user-writable auggie binaries — deferred as repo-wide hardening tracked separately; same pattern already ships in Copilot/Claude CLI detectors (@thatcatfromspace).
  • MCP cache sentinel / empty-result memoization — fixed with _AUGMENT_CACHE_UNSET (@thatcatfromspace).
  • MCP workspace walk duplicating user-home ~/.augment — fixed via _scanned_user_augment_dirs skip set (@thatcatfromspace).
  • Linux rules extractor missing per-user error guard — fixed with try/except (PermissionError, OSError) (@thatcatfromspace).
  • VS Code stable+nightly duplicate rows — fixed; at most one row emitted, stable preferred.
  • Symlinked .augment directories in project walks — fixed; symlink check runs before .augment dispatch in rules/MCP/skills walkers.
  • Managed permissions bypassing ownership gate — fixed; _augment_owned_by_user excludes managed-only scope from counting as user-owned data.
  • JetBrains _config_path mis-attribution under root scans — fixed via IDE-owner home derivation.
  • log_mcp_details may log MCP arg secrets — pre-existing shared helper used by sibling tools; not introduced by this diff (Claude).

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head 5333ad8e · 2026-06-26T06:23Z

@vigneshsubbiah16 vigneshsubbiah16 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛡️ Automated Security Review (consensus)

5 findings — 3 high-confidence, 2 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 HIGH — MCP config reads lack symlink containment

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:223
Impact: _read_mcp_config reads ~/.augment/settings.json and mcp*.json (user + project scope) with only is_file() — no symlinked_file_escapes_home — so a privileged all-users scan can follow out-of-home symlinks and emit arbitrary file contents as MCP config.
Fix: Reject paths where symlinked_file_escapes_home(config_path) before read_text(), matching augment_settings_extractor._parse_jsonc.
Reviewers: Claude, Cursor

🔴 HIGH — Symlinked ~/.augment parent bypasses leaf-only guard

scripts/coding_discovery_tools/constants.py:104 (and direct user-scope read sites: settings, rules, MCP)
Impact: symlinked_file_escapes_home returns safe when the leaf file is not a symlink; if ~/.augment itself is ln -s /Users/victim/.augment, reads of settings.json follow the dir symlink and ingest another user's config under the attacker's identity during root scans.
Fix: Resolve the full path (or walk ancestors) and verify the real target stays within the owning user's home, not only when the leaf is a symlink.
Reviewers: Claude, Lead

🔴 HIGH — Workspace MCP transform may execute attacker-controlled commands

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:231
Impact: Project .augment/settings.json is attacker-controlled; parsing flows into transform_mcp_servers_to_array, which can actively probe/spawn configured stdio MCP commands — a coercion vector during privileged discovery runs.
Fix: Confirm whether transform_mcp_servers_to_array executes commands; if yes, disable active probing for workspace/project scope or restrict to metadata-only collection during discovery.
Reviewers: Cursor

🟡 TRIAGE — MCP details logged at info level may leak secrets

scripts/coding_discovery_tools/ai_tools_discovery.py:1880
Impact: _process_augment_tool calls log_mcp_details; MCP server args often carry tokens/keys (--api-key, bearer values) that may end up in operational logs.
Fix: Redact or omit sensitive MCP args in log_mcp_details, or gate Augment logging behind a debug flag.
Reviewers: Cursor

🟡 TRIAGE — User hooks dropped when managed settings win precedence

scripts/coding_discovery_tools/ai_tools_discovery.py:1939
Impact: transform_settings_to_backend_format keeps only the highest-precedence scope; when org managed settings.json exists, user hooks in raw_settings are omitted from the payload despite being needed for risk classification.
Fix: When managed wins for toolPermissions, still merge user-scope hooks into the emitted raw_settings (or attach a separate user-hooks field).
Reviewers: Cursor

Previously acknowledged (not re-flagged)

  • Privileged scan executes user-writable auggie binaries — maintainer deferred as repo-wide hardening (parity with Copilot CLI / Claude detectors), not an Augment-only fix.
  • MCP cache sentinel / empty-None memoization — fixed with _AUGMENT_CACHE_UNSET; regression test added.
  • MCP workspace walk re-collecting ~/.augment as project scope — fixed by tracking scanned user-home .augment dirs; regression test added.
  • Linux rules extractor missing per-user try/except — fixed to match skills extractor.
  • Managed-only permissions bypassing ownership gate — fixed in _augment_owned_by_user (managed scope does not count as user-owned data).
  • VS Code-only / per-user canonical surface dropping user settings — fixed with _canonical_augment_surface_by_config keyed per _config_path.
  • Dual stable+nightly VS Code duplicate rows — fixed (prefer stable extension, emit one row).
  • JetBrains _config_path mis-attribution under root scans — fixed via _augment_owner_home_for_path.
  • Windows skills walk missing traverses_other_tool_config_dir — fixed; parity test added.
  • Symlinked .augment dirs in skills walk — fixed (symlink check before name dispatch, matching rules/MCP ordering).

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head 9e004cd3 · 2026-06-26T06:53Z

@vigneshsubbiah16

Copy link
Copy Markdown
Contributor

🛡️ Automated Security Review (consensus)

3 findings — 1 high-confidence, 2 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 HIGH — MCP config reads lack symlink containment

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:206-223
Impact: _read_mcp_config reads user/workspace settings.json and mcp*.json with only is_file() — unlike the hardened settings/rules/skills paths, symlinked configs can escape scope and disclose out-of-home file contents under privileged all-users scans.
Fix: Before read_text, reject paths where symlinked_file_escapes(config_path, <scope_root>) is true (config dir for user scope, project root for workspace scope).
Reviewers: Claude, Cursor

🟡 TRIAGE — MCP server commands/args logged at info level

scripts/coding_discovery_tools/ai_tools_discovery.py:1880
Impact: The new Augment path calls log_mcp_details, which logs full MCP command/argument strings that often carry API keys, bearer tokens, or connection secrets into operational log sinks.
Fix: Redact known secret-bearing flags/values in log_mcp_details, or log server names/counts only (ideally repo-wide; this mirrors the existing Copilot path).
Reviewers: Claude, Cursor

🟡 TRIAGE — Workspace MCP transform may execute untrusted stdio commands

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:231
Impact: Project .augment/settings.json is attacker-controlled repo content; passing it through transform_mcp_servers_to_array may actively probe/spawn configured MCP stdio commands during discovery, including under elevated scans.
Fix: Use parse-only extraction for discovery (no subprocess probes), or gate execution behind the same trust/sandbox policy used elsewhere for untrusted MCP configs.
Reviewers: Cursor

Previously acknowledged (not re-flagged)

  • Privileged execution of user-writable auggie binaries — maintainer deferred to a separate repo-wide hardening change (same pattern already ships in Copilot/Claude CLI detectors).
  • MCP cache None sentinel collision — fixed with _AUGMENT_CACHE_UNSET memoization.
  • Linux rules extractor missing per-user error guard — fixed with try/except (PermissionError, OSError) around each extract_for_user.
  • Workspace walk re-reading ~/.augment as project MCP — fixed by tracking scanned user-home .augment dirs and skipping them in the workspace walk.
  • Rules/settings/skills symlink containment (dirs + files) — addressed via symlinked_file_escapes, symlinked-dir ordering before .augment dispatch, and OS-specific _extract_single_rule_file wrappers.
  • Managed-permissions ownership gate / per-user canonical surface / JetBrains owner attribution / stable-vs-nightly VS Code dedup — addressed in current orchestration and detector logic with regression tests.

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head cbafbba7 · 2026-06-26T07:01Z

@thatcatfromspace thatcatfromspace force-pushed the web-4950-augment-discovery branch from cbafbba to 5333ad8 Compare June 26, 2026 08:51
@vigneshsubbiah16

Copy link
Copy Markdown
Contributor

🛡️ Automated Security Review (consensus)

3 findings — 1 high-confidence, 2 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 HIGH — User-scope ~/.augment reads lack symlink/containment guards (privileged scan disclosure)

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:206, augment_settings_extractor.py:59, augment_rules_extractor.py:291, augment.py:46
Impact: Under root/MDM all-users scans, a user can symlink ~/.augment, settings.json, mcp*.json, or rule/skill files to another readable path; the scanner follows symlinks (is_file()/read_text() with no symlinked_file_escapes / home containment) and attributes leaked MCP, permissions, rules, or file content to the attacker's row.
Fix: Before every user-scope read, resolve() the path and reject when the target escapes user_home (reuse the containment helper already used in project walks); also reject a symlinked ~/.augment directory itself in _resolve_augment_dir / user extractors.
Flagged by: Cursor (Bugbot + Agentic Security Review), Greptile (P1 security), Claude

🟡 TRIAGE — Project-scope MCP configs may drive active MCP probing

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:231
Impact: Workspace .augment/settings.json (attacker-controlled repo content) is parsed and passed to transform_mcp_servers_to_array, which may spawn or probe configured stdio MCP commands during discovery—risk scales with what that shared helper does under elevated scans.
Fix: Confirm transform_mcp_servers_to_array is parse-only in discovery; if not, disable execution for project-scope configs or gate on the same trusted-path policy used elsewhere.
Flagged by: Cursor (Agentic Security Review)

🟡 TRIAGE — Augment MCP logging may emit secrets

scripts/coding_discovery_tools/ai_tools_discovery.py:1880
Impact: _process_augment_tool calls log_mcp_details at info level; MCP server command lines/args often carry API keys or tokens, which can land in operational logs.
Fix: Redact sensitive args in log_mcp_details, downgrade to debug, or omit args for Augment (match any existing redaction used by other tools).
Flagged by: Cursor (Agentic Security Review)

Previously acknowledged (not re-flagged)

  • Auggie CLI executed from user-writable paths (~/.local/bin, nvm, etc.) under root scans@thatcatfromspace deferred as repo-wide hardening (parity with Copilot CLI / Claude detectors); tracked separately, not Augment-only.
  • MCP cache None sentinel collision, workspace walk re-collecting ~/.augment as project scope, dual VS Code rows, managed-permissions ownership-gate bypass, JetBrains _config_path mis-attribution, Linux rules per-user abort, project-walk symlinked .augment / skills dirs — fixed in-thread with regression tests; not re-raised.
  • _build_record only reads top-level mcpServers (misses nested form) — Greptile/Claude treat as metadata/completeness gap affecting risk visibility, not an exploitable issue; not re-raised as security.
  • User hooks omitted when managed settings.json wins precedence — follows existing transform_settings_to_backend_format scope precedence (managed > user); product behavior, not re-raised.

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head a3ff12ca · 2026-06-26T09:15Z

for mcp_file in sorted(augment_dir.glob(_MCP_FILE_GLOB)):
config = self._read_mcp_config(mcp_file, str(augment_dir), "user")
if config:
configs.append(config)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Symlinked user augment dir read

High Severity

User-scope extraction opens ~/.augment via _resolve_augment_dir without rejecting a symlinked config directory. Under privileged all-users scans, a profile can point .augment at another user’s tree so MCP, rules, and settings reads follow the link and emit that user’s policy and content under the wrong home label.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a3ff12c. Configure here.

@thatcatfromspace thatcatfromspace force-pushed the web-4950-augment-discovery branch from a3ff12c to 5333ad8 Compare June 26, 2026 09:44
The skills project walk symlink-checks the parent .augment dir but then used
type_dir.is_dir() on the skills/commands subdir, which follows symlinks — so
under a root MDM scan a user could point .augment/skills at an arbitrary dir and
have the scanner traverse it. Add the matching `not type_dir.is_symlink()` guard
(mirrors the parent-dir guard in the same method). All OSes via the inherited
macOS walk. Adds a regression test (symlinked .augment/skills not traversed;
real one still collected).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

There are 4 total unresolved issues (including 3 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8f2aeb1. Configure here.

if size > _MAX_SETTINGS_BYTES:
logger.warning(f"Skipping oversize Augment settings file {path} ({size} bytes)")
return None
raw = path.read_text(encoding="utf-8", errors="replace")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Symlinked config reads lack containment

High Severity

Augment's settings and MCP config file readers (e.g., for settings.json, mcp*.json) follow symlinks. This allows users, particularly during root-aware scans, to link to files outside their expected directories, leading to the collection of unintended host content. Directory walks correctly skip symlinked folders, but not symlinked files.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8f2aeb1. Configure here.

@vigneshsubbiah16 vigneshsubbiah16 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛡️ Automated Security Review (consensus)

7 findings — 5 high-confidence, 2 to triage. Reviewers: Cursor, Claude, Semgrep, Gitleaks.

🔴 HIGH — MCP config reader follows symlinks without containment

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:218
Impact: In root/MDM all-users scans, a user can symlink ~/.augment/settings.json or mcp*.json to another readable file and have its MCP config parsed and attributed under the attacker's home.
Fix: Before read_text() in _read_mcp_config, reject paths where symlinked_file_escapes_home (same guard as sibling extractors).
Reviewers: Cursor, Claude, Greptile

🔴 HIGH — Symlinked ~/.augment directory enables cross-user ingestion

scripts/coding_discovery_tools/macos/augment/augment_rules_extractor.py:115 (also augment_settings_extractor.py:151, augment_mcp_config_extractor.py:98)
Impact: If ~/.augment is a directory symlink to another user's config, regular files inside are read without escaping the owning home; rules/settings/MCP from the target are emitted under the symlink owner's identity.
Fix: After _resolve_augment_dir, verify the resolved path stays under user_home (reject directory symlinks that escape the home boundary) before any user-scope walk/read.
Reviewers: Cursor

🔴 HIGH — Settings JSON read follows symlinks

scripts/coding_discovery_tools/macos/augment/augment_settings_extractor.py:59
Impact: _parse_jsonc uses is_file() then read_text() with no symlink check, so a symlinked ~/.augment/settings.json can disclose arbitrary root-readable JSON into raw_settings during privileged scans.
Fix: Reject symlinked settings paths that escape the owning user's home before stat()/read_text().
Reviewers: Cursor

🔴 HIGH — Rule/guideline files follow symlinks outside tree

scripts/coding_discovery_tools/macos/augment/augment_rules_extractor.py:304
Impact: _add_rule_file accepts symlinked .md/.mdx (and repo-root AGENTS.md/CLAUDE.md/.augment-guidelines), letting a crafted symlink read arbitrary host files into discovery payloads.
Fix: Skip item.is_symlink() (and apply symlinked_file_escapes against the project/home root) before calling extract_single_rule_file.
Reviewers: Cursor

🔴 HIGH — Workspace MCP transform may execute untrusted stdio commands

scripts/coding_discovery_tools/macos/augment/augment_mcp_config_extractor.py:231
Impact: Project .augment/settings.json is attacker-controlled; transform_mcp_servers_to_array can probe/spawn configured MCP stdio commands during discovery, including under elevated scans.
Fix: Treat workspace MCP configs as untrusted metadata only (parse without execution), or gate execution behind the same trust model used for other tools' MCP scanners.
Reviewers: Cursor

🟡 TRIAGE — MCP args may leak into operational logs

scripts/coding_discovery_tools/ai_tools_discovery.py:1880
Impact: _process_augment_tool calls log_mcp_details at info level; MCP command/args often carry API keys or tokens into log aggregation.
Fix: Redact sensitive args in log_mcp_details, downgrade to debug, or omit arg values for Augment (match any existing redaction used elsewhere).
Reviewers: Cursor

🟡 TRIAGE — Symlinked skill/command files not rejected at read time

scripts/coding_discovery_tools/macos/augment/augment_skills_extractor.py:129
Impact: Directory symlink guards were added, but shared skill/command helpers still accept is_file() entries that can be symlinks, enabling out-of-tree reads of markdown content.
Fix: Reject symlinked skill/command files (and apply containment vs. project/home root) before content extraction in the Augment skills path.
Reviewers: Cursor

Previously acknowledged (not re-flagged)

  • Privileged scan executes user-writable auggie binary (macos/augment/augment.py:202-216) — @thatcatfromspace: deferred as separate repo-wide hardening (parity with Copilot CLI / Claude detectors); fix only Augment would leave siblings exposed. Tracked separately.
  • MCP cache sentinel / workspace ~/.augment re-collection@thatcatfromspace: fixed (_AUGMENT_CACHE_UNSET + skip already-scanned user ~/.augment in workspace walk).
  • Linux rules scan abort on per-user OS errors@thatcatfromspace: fixed (try/except per home, parity with skills extractor).

🤖 consensus review · reviewers: Cursor,Claude,Semgrep,Gitleaks · head 8f2aeb1c · 2026-06-26T09:55Z

@thatcatfromspace thatcatfromspace merged commit 48b6cda into staging Jun 26, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants