Skip to content

PE3 fires HIGH on credential vocabulary in prose: a SKILL.md containing only the word keyring is Privilege Escalation #396

Description

@Mark2Mac

Summary

PE3 / Credential Access fires at HIGH on credential vocabulary in Markdown prose, with no
path-like or code context required. A SKILL.md whose entire body is the single word keyring
is reported as Privilege Escalation.

This is the same family as #145 and #251, both closed as completed. Those addressed .env
references; the underlying behaviour — a bare keyword in documentation prose scoring HIGH — is
still present on main.

Reproduction

mkdir -p /tmp/pe3/solo-parola
cat > /tmp/pe3/solo-parola/SKILL.md <<'EOF'
---
name: solo-parola
description: minimal case.
---
keyring
EOF

uvx --from 'git+https://github.com/NVIDIA/skillspector' skillspector scan /tmp/pe3/solo-parola --no-llm

Result (v2.9.6, git HEAD; identical on the released 2.5.1):

{
  "id": "PE3",
  "category": "Privilege Escalation",
  "pattern": "Credential Access",
  "severity": "HIGH",
  "confidence": 0.7,
  "finding": "keyring",
  "location": {"file": "SKILL.md", "start_line": 5},
  "explanation": "Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts."
}

Note that explanation says "Code accesses credential files". There is no code and no file
access — the document contains one word.

Matrix (v2.9.6, --no-llm, one SKILL.md each)

Body of the Markdown file Result
keyring PE3 / HIGH
Keychain PE3 / HIGH
"Read credentials from a keyring at runtime, not from fixed variables." PE3 / HIGH
"Never put an access token in cleartext in a versioned file." PE3 / HIGH
"Never commit the .env file to the repository." PE3 / HIGH
"The /etc/passwd file lists system users and is world-readable." PE3 / HIGH
"This skill formats markdown tables and touches nothing." clean

Six out of six. Every one of them is a sentence telling the reader not to mishandle secrets.

Why this matters

The failure mode is specific: a skill whose subject is secure credential handling cannot be
documented without scoring HIGH. Any pre-install gate that keys on the worst finding — which is
the correct thing for a gate to do, since risk_assessment.severity is normalised and can read
LOW while issues[] contains HIGH — will refuse to install security documentation.

In my own use this is the difference between a gate that blocks poisoned skills and a gate the
user learns to override. A shield that stops legitimate content is a shield people route around.

Suggested direction

PE3 currently matches credential-adjacent vocabulary anywhere in the file. Two options, not
mutually exclusive:

  1. Require context, not vocabulary. Fire on an access shapeopen(...), cat, read,
    a redirect, an assignment from a path — rather than on the presence of a noun. keyring in a
    sentence is a topic; open(os.path.expanduser("~/.aws/credentials")) is an access.
  2. Let the file surface carry weight. A non-executable Markdown file that is documentation is
    not the same evidence as a .py in the same skill. This is what [Feature] Expose the file surface a finding landed on (code / instructions / docs / tests / config) #326 asks for, and PE3 is a
    good example of why: the same string deserves a different severity depending on whether it sits
    in prose or in a code path.

The current remediation text already hints at the gap — "For docs, use placeholder paths"
which asks documentation authors to write worse documentation so a static rule stays quiet.

Environment: v2.9.6 (git HEAD) and v2.5.1 (PyPI), Python 3.13, Linux, --no-llm (static only).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions