← All MCP servers
MCP server

ArtifactSmith

mcp:vrijsinghani/artifactsmith

Turns agent output into versioned web pages, PDFs, Word docs, spreadsheets and Markdown.

Verdict
Suspicious

Risky behavior the analysis could not rule out.

Analyzed Oct 26, 2026, 13:45 UTC at 50cde81
1
findings
high
highest severity
1
threat classes
264
files scanned
2,829/2,829
checks satisfied
0
package advisories

Why this verdict

mcp-server . Suspicious
  • inconclusive: gap manifest_unparseable at compose.yaml
skill .cursor/skills/artifactsmith-security-checklist No issues found
  • benign: 25 checks satisfied, no findings for skill:.cursor/skills/artifactsmith-security-checklist
skill .cursor/skills/security-best-practices No issues found
  • benign: 39 checks satisfied, no findings for skill:.cursor/skills/security-best-practices
skill .cursor/skills/security-threat-model Suspicious
  • suspicious: unverified finding skill:.cursor/skills/security-threat-model:.cursor/skills/fetch-upstream.sh:13:SUPPLY

Security findings 1

Supply chain

highUnverifiedlow confidence

The undeclared env vars ARTIFACTSMITH_OA_URL and ARTIFACTSMITH_OA_SHA (and the TOB equivalents) let the upstream repo and pin be redirected away from the official openai/skills commit, so an attacker who controls the environment could substitute the fetched instruction content.

readonly OA_URL="${ARTIFACTSMITH_OA_URL:-https://github.com/openai/skills.git}"
conceal:remotevector:code

Open questions 3

What the analysis could not settle from the code alone.

Does fetch-upstream.sh fetch only pinned SHAs from the stated upstream repos and verify blobs, or can it pull mutable content? The shown portion is mostly comments.
Supply chain
[file request scripts/run-security-semgrep.sh] The script's own comments say run-scans.sh clones third-party Semgrep rules from https git URLs at whatever HEAD it gets. Does this script do that unpinned clone, and does any fetched content reach agent instructions or get executed?
Supply chain
Does fetch-upstream.sh actually pin the upstream content to a commit SHA and verify blobs, and does it fetch only from trusted hosts? Its comments say so, but only partial content is shown.
Supply chain

Execution chain 132

What it calls, runs, installs, reads and writes, with the line that does it.

Environment variables 4

Files read 13

.env.example
generated AM_STORE_KEY / AM_STORE_SECRET in .env
wrote .env from .env.example

GitHub repositories 12

qingyuna/answer-me-with-html
qingyuna/answer-me-with-html
qingyuna/answer-me-with-html
qingyuna/answer-me-with-html
vrijsinghani/artifactsmith
vrijsinghani/artifactsmith
vrijsinghani/artifactsmith
vrijsinghani/artifactsmith
vrijsinghani/artifactsmith
vrijsinghani/artifactsmith
vrijsinghani/artifactsmith
vrijsinghani/artifactsmith

Network calls 7

<dynamic>
src/artifactsmith/llm.py:308 · via:call_responses
<dynamic>
github.com

URLs 85

http://127.0.0.1:*/callback
http://127.0.0.1:*/callback
http://127.0.0.1:8080/healthz
http://127.0.0.1:8780
http://127.0.0.1:8780
http://127.0.0.1:8780
http://127.0.0.1:8780
http://127.0.0.1:8780/mcp
http://127.0.0.1:8781
http://127.0.0.1:8781
http://127.0.0.1:8781
http://127.0.0.1:8781
http://127.0.0.1/callback
http://fake-chat-llm:8080
http://localhost:*/callback
http://localhost:*/callback
http://localhost/callback
http://storage:9000
http://storage:9000
http://www.apache.org/licenses/
http://www.apache.org/licenses/
http://www.apache.org/licenses/LICENSE-2.0
http://www.w3.org/XML/1998/namespace
https://api.openai.com
https://api.openai.com
https://api.openai.com
https://api.openai.com
https://api.openai.com
https://api.openai.com/v1
https://api.openai.com/v1
https://artifactsmith.neuralami.ai/mcp
https://artifactsmith.neuralami.ai/mcp
https://artifactsmith.neuralami.ai/mcp
https://artifactsmith.neuralami.ai/mcp
https://artifactsmith.neuralami.ai/mcp
https://artifactsmith.neuralami.ai/mcp
https://artifactsmith.neuralami.ai/mcp
https://artifactsmith.neuralami.ai/s/44mswkknyq4rvznt/
https://artifactsmith.neuralami.ai/s/5d9u9rth7ete55i8/
https://artifactsmith.neuralami.ai/s/8764hbpn3dtfiqp9/
https://artifactsmith.neuralami.ai/s/8764hbpn3dtfiqp9/
https://artifactsmith.neuralami.ai/s/hjuve9f54jqjcwcv/
https://artifactsmith.neuralami.ai/s/pfe9mq4yserk3dym/
https://artifactsmith.neuralami.ai/s/qift8jdku8ncbj73/
https://artifactsmith.neuralami.ai/s/s27y44saiqz8rycy/
https://artifactsmith.neuralami.ai/s/sq8fgpxy5bth98qe/
https://artifactsmith.neuralami.ai/s/tc2aciqyfgqxbugx/
https://artifactsmith.neuralami.ai/s/tjnjns5su7chqtuv/
https://artifactsmith.neuralami.ai/s/xsxxtwrvgev7fvc6/
https://artifactsmith.neuralami.ai/try
https://artifactsmith.neuralami.ai/try
https://artifactsmith.neuralami.ai/try
https://chatgpt.com/connector_platform_oauth_redirect
https://chatgpt.com/connector_platform_oauth_redirect
https://chatgpt.com/connector/oauth/
https://claude.ai/api/mcp/auth_callback
https://claude.ai/api/mcp/auth_callback
https://github.com/QingYunA/answer-me-with-html
https://github.com/QingYunA/answer-me-with-html
https://github.com/QingYunA/answer-me-with-html
https://github.com/QingYunA/answer-me-with-html
https://github.com/vrijsinghani/artifactsmith
https://github.com/vrijsinghani/Artifactsmith
https://github.com/vrijsinghani/Artifactsmith
https://github.com/vrijsinghani/Artifactsmith
https://github.com/vrijsinghani/Artifactsmith
https://github.com/vrijsinghani/Artifactsmith
https://github.com/vrijsinghani/Artifactsmith
https://github.com/vrijsinghani/artifactsmith/issues
https://glama.ai/mcp/schemas/server.json
https://vscode.dev/redirect
https://vscode.dev/redirect
https://www.cursor.com/agents/mcp/oauth/callback

Linked repositories 1

GitHub repositories it links to or installs from, and whether their names can be taken over.

Refuted findings 8

Candidates the review stage examined and rejected, kept for transparency.

Supply chain

criticalRefutedlow confidence

The attribution doc directs the agent/user to run a fetch script to pull companion reference files from upstream rather than shipping them, making instructions loaded into context mutable remote content.

`bash .cursor/skills/fetch-upstream.sh openai-best-practices`
Why it was refuted

The doc openly declares that references are fetched by the script, and the script pins the official openai/skills commit. This is declared, pinned retrieval of upstream content, not hidden mutable content.

Supply chain

criticalRefutedmedium confidence

The skill instructs the agent to run a bundled script at skill runtime that fetches reference content from remote upstream sources (not shipped in the repo), and the agent then loads and follows those fetched instructions, so behavior depends on remote content.

REFS=$(bash .cursor/skills/fetch-upstream.sh openai-best-practices)
Why it was refuted

The run-time fetch is declared in SKILL.md and pinned to a fixed official commit SHA, so the fetched references are immutable upstream content rather than mutable remote instructions.

Code execution

criticalRefutedlow confidence

SKILL.md states that it fetches companion references at run time by executing a shell script, an auto-run step outside the user's task whose content and network behavior are not visible in this unit.

This copy fetches companion `references/` at run time with `bash .cursor/skills/fetch-upstream.sh`
Why it was refuted

The line declares the fetch script openly, and the script is shipped and visible with pinned defaults. There is no concealed or undeclared execution.

Supply chain

criticalRefutedmedium confidence

The skill tells the agent to run a helper script that fetches the prompt template from upstream at run time, then to follow that fetched file's output contract, so the agent's instructions come from content outside the artifact.

TM=$(bash .cursor/skills/fetch-upstream.sh openai-threat-model)
Why it was refuted

The fetch of the prompt template is declared in SKILL.md and pinned to a fixed official openai/skills commit, so the instructions are not mutable remote content.

Supply chain

highRefutedlow confidence

The script fetches upstream skill trees from GitHub at run time, and the repository URLs and pinned commit SHAs can be overridden through environment variables, so the fetched skill instructions and scripts could come from a redirected source.

readonly TOB_URL="${ARTIFACTSMITH_TOB_URL:-https://github.com/trailofbits/skills.git}"
Why it was refuted

The default is a pinned commit SHA of the official upstream repo. Overriding the URL needs control of the local environment, which already gives an attacker more power than the override does.

Supply chain

highRefutedlow confidence

Undeclared environment variables (ARTIFACTSMITH_OA_URL, ARTIFACTSMITH_OA_SHA, and the TOB equivalents) let the upstream repo URL and commit pin be redirected to an arbitrary source. Whatever that source returns is then loaded as skill instructions. The defaults are pinned and the override is not documented to users.

ARTIFACTSMITH_OA_URL:-https://github.com/openai/skills.git
Why it was refuted

The OA defaults are pinned to a specific official commit. The env override is an operator-controlled configuration knob, not an attacker-reachable path or concealed behavior.

Manipulation

mediumRefutedlow confidence

Shared HTML pages get a credit footer appended at serve time, styled with inline !important so page CSS cannot hide it, so viewers see content the page author did not write.

Inline !important beats a page rule that hides footer, a, or this id.
Why it was refuted

This is a documented, toggleable branding footer on the share view, not deceptive or harmful manipulation. Stored bytes are unchanged and the visible text is just the product name linked to the repo.

Manipulation

mediumRefutedlow confidence

When a configuration flag is on, shared HTML pages are modified at serve time by injecting a branding footer with forced !important styles so page rules cannot hide it; this is a documented, toggleable credit line and appears to be benign branding.

footer = f'<footer id="{CREDIT_ID}" style="{_FOOTER_STYLE}">{link}</footer>'
Why it was refuted

The footer is an openly named, config-gated credit line and the finding itself calls it benign branding. It is neither concealed nor harmful.

Coverage gaps 1

Parts of the artifact the static analysis could not fully examine.

manifest_unparseable yaml: YAML aliases are not permitted
compose.yaml