Announcing Beacon: Self-improving memory for coding agents
← All skills
Skill

fal-assets

skill:rehan-remade/universal-modder#fal-assets

Generate game assets with fal (fal.ai) through the fal MCP server, the `um fal` CLI (REST) or `fal api`. Covers sprites and icons with transparent backgrounds, consistent variants and animation frames, pixel art, seamless textures, PBR material maps, image-to-3D models, remeshing, auto-rigging, sound effects, music, voice lines, and trailer or cutscene video. Use whenever a mod needs new art, audio or 3D models, or the user mentions fal, generating sprites, textures, models, SFX or music for a game.

Verdict
Inconclusive

The analysis could not cover enough of the artifact to decide.

Analyzed Oct 27, 2026, 21:34 UTC at a2e7c9b

Dispute security verdict

If you believe this verdict is incorrect, submit a dispute and we'll review it.

0
findings
—
highest severity
0
threat classes
855
files scanned
38/38
checks satisfied
0
package advisories

Why this verdict

  • inconclusive: unresolved question on CRED
  • inconclusive: unresolved question on EXFIL

Security findings 0

No individual findings recorded

The inconclusive verdict rests on the open questions and coverage gaps below; 5 candidate findings were refuted on review.

Open questions 21

What the analysis could not settle from the code alone.

The `um` CLI invoked throughout (um fal, um fal key set/status, um comfy, um sprixen, um voidless, um publish check) is not among the shown units; its key storage, upload destinations, and side effects cannot be verified from this evidence.
Credential access
The PY-CLAIM-CONTRADICTION detector leads (file_write of --type/key=value/fal_manifest.jsonl allegedly contradicting 'never write the key into mod files or configs') were checked against the cited lines and appear to be false positives (key=value are API input placeholders and the manifest stores endpoint/inputs/seed/request id, not the key); confirm no code path writes FAL_KEY into files.
Persistence
[file request bin/um] Where do `um fal key set` / `um fal key status` persist FAL_KEY (keyring via secret-tool, ~/.secrets/fal-key, .env), and which hosts receive the key and the uploaded local inputs from `um fal`, `um sprixen`, and `um voidless` — is anything sent beyond fal.ai, Sprixen, or Voidless endpoints?
Credential access
[file request bin/um] Can the FAL_KEY value reach `<out>/fal_manifest.jsonl`, mod files, or any config written by `um fal` recipes, contradicting the skill's claim that keys are never written into mod files or configs?
Credential access
[file request .mcp.json] Show the full .mcp.json: does it register only fal's hosted server at https://mcp.fal.ai/mcp with the bearer token taken from the FAL_KEY environment variable, with no literal key, extra servers, commands, or instructions?
Credential access
[file request gemini-extension.json] Show the full gemini-extension.json: does it register only fal's hosted MCP server with the key taken from the FAL_KEY environment variable, with no literal key, extra servers, or embedded instructions?
Credential access
[file request opencode.json] Show the full opencode.json: does it register only fal's hosted MCP server with the key taken from the FAL_KEY environment variable, with no literal key, extra servers, or embedded instructions?
Credential access
[file request um/um] If this file implements the `um` CLI, does it restrict uploads to user-specified input files, send the key and inputs only to fal.ai/Sprixen/Voidless endpoints, and keep FAL_KEY out of fal_manifest.jsonl and every written file?
Data exfiltration
[file request um/__main__.py] If this file implements the `um` CLI entry point, does it restrict uploads to user-specified input files, send the key and inputs only to fal.ai/Sprixen/Voidless endpoints, and keep FAL_KEY out of fal_manifest.jsonl and every written file?
Data exfiltration
[file request .mcp.json] Does the pre-configured Claude Code MCP entry point only at fal's official hosted server (https://mcp.fal.ai/mcp) and keep the API key out of the file (env reference only)?
Credential access
[file request gemini-extension.json] Does the pre-configured Gemini CLI extension point only at fal's official MCP server and embed no credential material or extra instructions?
Credential access
[file request opencode.json] Does the pre-configured OpenCode MCP entry point only at fal's official MCP server and embed no credential material or extra instructions?
Credential access
[file request um] Where is the `um` CLI (`um fal`, `um fal key set`, `um fal run`, `um sprixen`, `um voidless`) implemented, and does it restrict uploads to user-specified input files, keep FAL_KEY out of written files, and write only the described fal_manifest.jsonl?
Data exfiltration
[file request um] The skill instructs the agent to run `um fal`, `um fal key set`, `um sprixen`, `um voidless`, `um publish check`. Does the `um` CLI send FAL_KEY only to the declared fal/Sprixen/Voidless endpoints, where does `um fal key set` persist the key, and can the key value reach `fal_manifest.jsonl`, mod files, or configs (which would contradict claim D4)?
Credential access
[file request .mcp.json] SKILL.md line 20 says the repo pre-configures fal's MCP server for Claude Code in `.mcp.json`. Does that shipped file configure only fal's hosted MCP endpoint with the key taken from the FAL_KEY environment variable, with no literal key and no extra servers or instructions?
Credential access
[file request gemini-extension.json] SKILL.md line 23 lists `gemini-extension.json` as the repo's pre-configuration for Gemini CLI. Does it configure only fal's hosted MCP endpoint with the key from the FAL_KEY environment variable, with no literal key or extra servers?
Credential access
[file request opencode.json] SKILL.md line 24 lists `opencode.json` as the repo's pre-configuration for OpenCode. Does it configure only fal's hosted MCP endpoint with the key from the FAL_KEY environment variable, with no literal key or extra servers?
Credential access
[file request .mcp.json] Does this project MCP config register only fal's server at https://mcp.fal.ai/mcp with the bearer token taken from the FAL_KEY environment, with no extra servers, commands, or instructions?
Persistence
[file request gemini-extension.json] Does this Gemini CLI extension config register only fal's MCP server, with no extra servers, commands, or instructions?
Persistence
[file request opencode.json] Does this OpenCode config register only fal's MCP server, with no extra servers, commands, or instructions?
Persistence
[file request bin/um] Where do `um fal key set` / `um fal key status` store the key (keyring, ~/.secrets/fal-key, .env) and which hosts receive the key and the uploaded local inputs from `um fal` recipes — is anything sent beyond fal.ai endpoints?
Credential access
Refuted findings 5

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

Credential access

criticalRefutedmedium confidence

The setup section steers the agent through a multi-source credential-discovery chain (agent environment, Linux keyring via secret-tool, owner-only ~/.secrets/fal-key, working-folder .env) and directs it at hidden per-agent configuration files (.mcp.json, .codex/config.toml, .cursor/mcp.json, .vscode/mcp.json, ~/.codex/config.toml), credential and agent-config access broader than the declared asset-generation task; the targets appear to be the wrapped fal service's own key and disclosed in-repo MCP configs, so this is plausibly honest setup.

an owner-only `~/.secrets/fal-key` where there's no `secret-tool`
Why it was refuted

Every credential source named is the wrapped fal service's own FAL_KEY resolution order (the keyring lookup is scoped to 'service fal.ai key api' and ~/.secrets/fal-key holds the key the human stored via 'um fal key set'), and the .env read and per-agent MCP config paths are declared in D3/D5/D13 and listed openly, so the wrapped-service-key carve-out plus the declarations defeat the finding.

Credential access

criticalRefutedlow confidence

The skill points the agent at hidden per-agent MCP configuration files (.mcp.json, .codex/config.toml, .cursor/mcp.json, .vscode/mcp.json, gemini-extension.json, opencode.json), three of whose contents are not shown in this artifact.

- Claude Code: `.mcp.json`
Why it was refuted

The skill's references to the per-agent config files are the openly declared setup of the declared fal hosted server with env-based auth ('The repo pre-configures it for each agent:'), and every served sibling config registers only https://mcp.fal.ai/mcp reading FAL_KEY from the environment (no extra servers, commands, hooks, or non-fal endpoints), so the flagged behavior falls under the declared-core-capability and env-API-key carve-outs with no credential exposure and no chain beyond fal's official endpoint; the three unserved files were returned NOT CONSUMED and no harmful content in them is demonstrated.

Persistence

criticalRefutedmedium confidence

The skill instructs registering an MCP server into agent control-plane configuration (`claude mcp add --transport http fal-oauth https://mcp.fal.ai/mcp-relay`, `codex mcp add fal-oauth`, and `[mcp_servers.fal]` in ~/.codex/config.toml), which writes MCP registrations the client will auto-connect to; the destinations shown are fal's official hosted endpoints, so this is a disclosed control-plane write for the declared capability.

Claude Code: `claude mcp add --transport http fal-oauth https://mcp.fal.ai/mcp-relay`, then
Why it was refuted

Every registration target is fal's official hosted endpoint (mcp.fal.ai/mcp-relay or mcp.fal.ai/mcp) and each command and the ~/.codex/config.toml block are declared verbatim in D10-D13, so this is disclosed setup for the declared fal MCP capability, not an undeclared or covert control-plane write.

Data exfiltration

criticalRefutedlow confidence

The `um fal` recipes upload local input files to the fal.ai API, so any file referenced by a recipe leaves the host, with the destination being the declared fal service.

It uploads local inputs,
Why it was refuted

Uploading local input files is inherent to the declared recipes (image-to-3D, edit with --ref base.png) and is declared verbatim in D21/D22, with the destination being the wrapped fal service itself, so the declared-core-capability carve-out and the declarations defeat the exfiltration reading.

Supply chain

highRefutedlow confidence

The skill instructs installing the fal SDK with an unpinned `pip install fal`, so the remote code the agent would later execute via `fal api` can change without review.

**CLI alternatives:** `pip install fal` gives `fal api <endpoint> key=value key:=json`
Why it was refuted

The exact instruction is declared verbatim in D19 and installs the wrapped service's own official SDK from the official registry for the declared `fal api` interface, so nothing is undeclared, concealed, or contradicted; the generic unpinned-version concern fails the undeclared gate, and the package's own code is out of scope.

Coverage gaps 66

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

context:unanalyzable_binary binary content is only byte-scanned
examples/aoe2-de-civ/assets/gen/drone.glb
context:unanalyzable_binary binary content is only byte-scanned
examples/aoe2-de-civ/assets/gen/robotaxi.glb
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineArgumentException.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineOption.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$AfterOptions.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$BeforeFirstSubCommand.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$KnownOptionParserState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$MissingOptionArgState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$OptionAwareParserState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$OptionParserState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$OptionString.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$ParserState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$UnknownOptionParserState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/ParsedCommandLine.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/ParsedCommandLineOption.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/internal/file/PathTraversalChecker.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/internal/file/locking/ExclusiveFileAccessManager.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/util/internal/WrapperCredentials.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/BootstrapMainStarter$1.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Download$DefaultDownloadProgressListener.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Download$ProxyAuthenticator.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Download.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/GradleUserHomeLookup.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/GradleWrapperMain$Action.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/GradleWrapperMain.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/IDownload.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Install$InstallCheck.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Install.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Logger.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/PathAssembler.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/PropertiesFileHandler.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/WrapperConfiguration.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-gta5-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/WrapperExecutor.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineArgumentException.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineOption.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$AfterOptions.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$BeforeFirstSubCommand.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$KnownOptionParserState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$MissingOptionArgState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$OptionAwareParserState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$OptionParserState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$OptionString.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$ParserState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser$UnknownOptionParserState.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/CommandLineParser.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/ParsedCommandLine.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/cli/ParsedCommandLineOption.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/internal/file/PathTraversalChecker.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/internal/file/locking/ExclusiveFileAccessManager.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/util/internal/WrapperCredentials.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/BootstrapMainStarter$1.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Download$DefaultDownloadProgressListener.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Download$ProxyAuthenticator.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Download.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/GradleUserHomeLookup.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/GradleWrapperMain$Action.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/GradleWrapperMain.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/IDownload.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Install$InstallCheck.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Install.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/Logger.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/PathAssembler.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/PropertiesFileHandler.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/WrapperConfiguration.class
context:unanalyzable_binary java_class content is only byte-scanned
examples/minecraft-outerwilds-passthrough/mc/gradle/wrapper/gradle-wrapper.jar!/org/gradle/wrapper/WrapperExecutor.class