project-scaffold — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited project-scaffold (Agent Skill) and scored it 45/100 (orange). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 3 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 3 flagged
A base64 string of 128+ characters appears in a documentation file. Encoded prompt injection hides the hostile instruction in base64 — invisible to keyword filters — and relies on the agent's ability to decode it at runtime. There is no normal authoring reason to embed a multi-hundred-byte base64 blob in skill docs.
*.sig, SIGNATURES) outside the documentation.Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Generates a complete, ready-to-open Python project: devcontainer config, VS Code settings and extensions, a full Makefile, pytest setup, commit-msg hook, and GitHub SSH wiring - everything configured and consistent from the first commit.
Ask the user for the following. Collect all answers before generating anything.
Required:
Optional (ask, but have sensible defaults):
_"Do you want a Dockerfile-based devcontainer (pre-baked image, fast container startup -- recommended) or a base image + postCreate script (standard, pulls fresh each time)?"_ Default: Dockerfile-based.
Ask: _"Do you have a GitHub SSH private key you'd like wired into the devcontainer? If so, what's the path on your host machine (e.g. ~/.ssh/id_ed25519)?"_ Default: skip if not provided.
Ask: _"Any extra VS Code extensions you want pre-installed?"_
~/Code -- ask the user only if they want a different locationBased on the user's answer:
Generate a .devcontainer/Dockerfile alongside devcontainer.json. The Dockerfile bakes all heavy system-level installs into image layers (cached after first build). The postCreate.sh is trimmed to only project-specific runtime steps (SSH key perms, workspace dirs, shell aliases, exporting and adding environment variables to the shell ~/.zshrc and ~/.bashrc files).
In devcontainer.json, replace "image": "..." with:
"build": {
"dockerfile": "Dockerfile",
"context": ".."
}See references/python.md for the Dockerfile template.
Use "image": "..." in devcontainer.json and run the full postCreate.sh on every new container. Simpler but slower -- every postCreate.sh run re-downloads and installs everything.
Read all of these before generating anything:
| File | Purpose |
|---|---|
references/python.md | devcontainer.json, Dockerfile, postCreate.sh, boilerplate |
references/common.md | Index of all templates + postStartCommand inline |
references/makefile.template.md | Full Makefile -- copy and substitute <PROJECT_NAME> |
references/gitignore.template.md | Full .gitignore -- use as-is |
references/pyproject.template.toml | Full pyproject.toml -- substitute all <PLACEHOLDER> values |
references/readme.template.md | Full README.md -- substitute <PROJECT_NAME> |
references/commit-msg.template.sh | Full .githooks/commit-msg -- copy verbatim |
references/versions.md | All version pins -- read before writing Dockerfile/postCreate |
Create all files under ~/Code/<project-name> (or the user-specified root).
<project-name>/
├── .devcontainer/
│ ├── devcontainer.json
│ ├── Dockerfile <- only if Dockerfile-based mode chosen
│ └── scripts/
│ └── postCreate.sh
├── .vscode/
│ ├── extensions.json
│ └── settings.json
├── .github/
│ └── (empty, ready for workflows)
├── src/
│ └── __init__.py
├── tests/
│ ├── __init__.py
│ └── test_sample.py
├── Makefile
├── .gitignore
├── .githooks/
│ └── commit-msg
├── pyproject.toml
├── requirements.txt
├── requirements-dev.txt
├── .python-version
└── README.mdAlways generate a Makefile. See references/common.md -> makefile.template.md for the full template.
Required targets (all projects):
make help -- prints available targets (always first, always default)make check-sys-deps -- verify required system packages are on PATHmake check-venv -- verify the virtual environment is activatedmake venv -- creates .venv using the correct Python versionmake install -- installs requirements.txt + requirements-dev.txt into the active venvmake format -- runs black + isortmake lint -- runs ruff + mypymake typecheck -- runs mypymake test -- runs pytest with coveragemake ci -- runs format + lint + typecheck + test in sequencemake clean -- removes build artifacts, caches, .venvConditional targets:
make github-check -- include only if the user provided an SSH key pathExtract the filename from the path (e.g. ~/.ssh/id_ed25519 -> id_ed25519). Call that <SSH_KEY_FILENAME> -- substitute it everywhere below.
devcontainer.json -- mount only that file, not the whole ~/.ssh directory:
"mounts": [
"source=<key-path>,target=/home/vscode/.ssh/<SSH_KEY_FILENAME>,type=bind,consistency=cached"
]postCreate.sh -- replace the SSH_KEY=<SSH_KEY_FILENAME> placeholder with the actual filename. The if block in the template then handles permissions and known_hosts automatically.
Makefile -- add the github-check target (see references/makefile.template.md).
devcontainer.json entirely -- do not mount ~/.sshSSH_KEY / if block from postCreate.shgithub-check Makefile targetAfter generating all files:
.gitignore -- from references/gitignore.template.md, use as-is.githooks/commit-msg -- from references/commit-msg.template.sh, copy verbatim, chmod +xREADME.md -- from references/readme.template.md, substitute <PROJECT_NAME>; remove the GitHub SSH section if no key was configured cd <project-name>
git init
git config core.hooksPath .githooks
git add .
git commit -m "chore: initial scaffold"Use this mode when the user wants to copy an existing scaffolded project to a new name -- no questions about devcontainer mode, SSH keys, or extensions. Everything is copied from the source project and the project name is substituted throughout.
<name>"<name>"<name>"Ask only:
<PROJECT_NAME> substitutions<destination-root>/<new-project-name>/.venv/, __pycache__/, .mypy_cache/, .ruff_cache/, .pytest_cache/,dist/, build/, *.egg-info/, .coverage, htmlcov/, *.pyc, .git/
Files to update (at minimum):
Makefile -- comment headerpyproject.toml -- name, [tool.mypy] source root if presentREADME.md -- title and any referencessrc/__init__.py -- docstring.devcontainer/devcontainer.json -- "name" field.devcontainer/scripts/postCreate.sh -- any echo banners.devcontainer/scripts/postStartCommand.sh -- comment headerAfter copying:
.git/ directory (start clean) cd <new-project-name>
git init
git config core.hooksPath .githooks
git add .
git commit -m "chore: initial scaffold"Print a one-line confirmation:
Cloned scaffold -> <destination-root>/<new-project-name>/
Substituted project name: <old-name> -> <new-name>
Git history reset -- run the commands above to initialise a fresh repo.Print a summary tree of everything created, then list the make targets available. Remind the user:
source .venv/bin/activatemake install to install dependenciesmake test to verify everything worksmake github-check to verify connectivity~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.