Back to skill

Security audit

Industry Deep-Dive Pipeline

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent article-production workflow, but its scanner can copy detected secrets or private paths into a report that the workflow packages for review.

Review this before installing if your drafts may contain credentials, private paths, customer data, or confidential company material. Treat 05-machine-gate.json as sensitive, redact secrets before scanning, and rerun the scanner on the final draft rather than relying only on the final validator's pass check.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/scan_draft_gates.py:54
Finding
Credential Values Are Copied into Machine-Gate Reports<![CDATA[ ## Vulnerability Details **File Location**: `scripts/scan_draft_gates.py`, lines 54–59 and 92–95 **Vulnerability Type**: Sensitive information exposure through diagnostic output **Risk Level**: High ### Vulnerable Code ```python def line_hits(text: str, name: str, pattern: re.Pattern[str], severity: str) -> list[dict]: hits = [] for line_no, line in enumerate(text.splitlines(), 1): if pattern.search(line): hits.append({"severity": severity, "category": name, "line": line_no, "excerpt": line.strip()[:180]}) return hits ``` The function is used directly for credential detection: ```python for name, pattern in SECRET_PATTERNS.items(): issues.extend(line_hits(draft, name, pattern, "P0")) issues.extend(line_hits(draft, "uuid", UUID_PATTERN, "P0")) issues.extend(line_hits(draft, "personal_path", PERSONAL_PATH_PATTERN, "P0")) ``` ### Technical Analysis The scanner correctly identifies several credential formats, including Notion tokens, GitHub tokens, OpenAI-style keys, and private-key headers. However, when a match is found, `line_hits()` copies up to 180 characters from the entire source line into the issue record. The issue records are subsequently serialized to the configured output file, normally `05-machine-gate.json`. Consequently, a credential discovered in the draft is not merely reported—it is duplicated into another artifact. Surrounding confidential text on the same line may also be copied. This violates secure diagnostic-output practices. Security scanners should report the type and location of a secret without reproducing its plaintext value. The project workflow also packages the machine-gate report with other deliverables, increasing the number of people and systems that may receive the exposed value. ### Attack Path 1. A draft contains a valid token, private credential, or confidential value matching one of the scanner patterns. 2. The required `scan_draft_gates.py` workflow is executed. 3. `line ...[truncated 1092 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never include an unredacted matching line in a secret-detection result. 2. Report only the secret category, line number, and a generic message such as `credential pattern detected`. 3. If correlation is necessary, store a non-reversible keyed digest or a carefully masked value rather than plaintext. 4. Redact the exact match before retaining any surrounding context. For example: ```python def line_hits( text: str, name: str, pattern: re.Pattern[str], severity: str, sensitive: bool = False, ) -> list[dict]: hits = [] for line_no, line in enumerate(text.splitlines(), 1): if pattern.search(line): excerpt = ( pattern.sub("[REDACTED]", line).strip()[:180] if sensitive else line.strip()[:180] ) hits.append({ "severity": severity, "category": name, "line": line_no, "excerpt": excerpt, }) return hits ``` 5. Invoke the function with `sensitive=True` for credentials, UUIDs, and personal paths. 6. Restrict permissions on generated reports and avoid including failed security reports in externally shared packages. 7. Add automated tests using synthetic tokens and verify that no portion of the original token appears in standard output or the JSON report. 8. Rotate any real credential that has already been processed by the vulnerable scanner and remove affected reports from retained artifacts. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/validate_case_bundle.py:66
Finding
Final Bundle Validation Can Be Bypassed with a Forged Machine-Gate Status<![CDATA[ ## Vulnerability Details **File Location**: `scripts/validate_case_bundle.py`, lines 66–75 and 115–117 **Vulnerability Type**: Integrity validation bypass caused by trusting attacker-controlled status metadata **Risk Level**: High ### Vulnerable Code ```python def validate_json(path: Path, issues: list[dict]) -> None: try: data = json.loads(read_text(path)) except Exception as exc: issues.append({"severity": "P0", "file": path.name, "message": f"invalid JSON: {exc}"}) return if not isinstance(data, dict): issues.append({"severity": "P1", "file": path.name, "message": "machine gate JSON must be an object"}) if data.get("status") not in {"pass", "passed"}: issues.append({"severity": "P0", "file": path.name, "message": "machine gate did not pass"}) ``` At the final stage, that check is applied without rerunning or authenticating the scan: ```python machine_gate = case_dir / "05-machine-gate.json" if args.stage == "final" and machine_gate.is_file(): validate_json(machine_gate, issues) ``` ### Technical Analysis The final validator treats the `status` property in `05-machine-gate.json` as authoritative. It does not establish that the report was generated by `scan_draft_gates.py`, verify the report schema, inspect its P0/P1 counts, require an empty issue list, or bind the report to the current contents of `07-final.md` and `01-fact-table.md`. Because the report is an ordinary writable JSON file, it can be replaced with a minimal object such as: ```json {"status": "pass"} ``` That object satisfies `validate_json()`. The validator then accepts the purported machine-gate result even if the final article contains credentials, personal paths, UUIDs, prohibited publication material, or unregistered numbers. There is also no integrity check preventing a legitimate report generated for an earlier draft from being reused after `07-final.md` is modified. This creates both forged-report and stale-re ...[truncated 1511 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make final validation rerun `scan_draft_gates.py` against the current `07-final.md`, fact table, and writing profile instead of trusting a preexisting status file. 2. Prefer importing shared scanner logic as a Python module rather than invoking a shell command. 3. If retaining report-based validation, define and enforce a strict schema requiring: - `status` equal to `pass`; - integer P0 and P1 counts equal to zero; - an empty `issues` collection; - an empty `unregisteredNumbers` collection; - expected scanner and schema versions; - cryptographic hashes of the scanned draft, fact table, and applicable profile. 4. Recompute the hashes during final validation and reject any mismatch. 5. Reject unknown or missing fields where they affect security decisions. A minimal `{"status":"pass"}` object must never be sufficient. 6. Write scan reports atomically and apply restrictive file permissions where appropriate. 7. Add negative tests covering: - a forged minimal pass report; - a report with `status: pass` but nonzero issue counts; - a report generated for a previous draft; - a final draft changed after scanning; - malformed top-level JSON values. 8. Ensure final validation scans `07-final.md`, not only an earlier draft, and regenerate the final machine-gate artifact after every revision. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep

Static analysis

No suspicious patterns detected.