Add Asqav Sign Action tool node#6614
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces the Asqav API credential and the Asqav Sign Action tool, allowing users to sign agent actions and obtain cryptographic compliance receipts. Feedback on the implementation highlights several key improvements: addressing a potential SSRF vulnerability by validating the user-configurable baseUrl against a deny list, validating the presence of the API key early, using the robust parseJsonBody utility instead of standard JSON.parse, and optimizing the workflow by allowing an optional agentId to prevent creating a new agent on every execution.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| } | ||
| } | ||
|
|
||
| const baseUrl = ((nodeData.inputs?.baseUrl as string) || DEFAULT_BASE_URL).replace(/\/+$/, '') |
There was a problem hiding this comment.
Since baseUrl is a user-configurable input, an attacker could supply an internal IP address or hostname (e.g., http://127.0.0.1 or AWS metadata endpoints) to perform a Server-Side Request Forgery (SSRF) attack. Call await checkDenyList(baseUrl) to validate the URL against Flowise's security policy before making any network requests.
const baseUrl = ((nodeData.inputs?.baseUrl as string) || DEFAULT_BASE_URL).replace(/\n+$/, '')
await checkDenyList(baseUrl)| import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' | ||
| import { getCredentialData, getCredentialParam } from '../../../src/utils' |
There was a problem hiding this comment.
Import parseJsonBody from ../../../src/utils to allow robust JSON parsing of the context input, and import checkDenyList from ../../../src/httpSecurity to protect against SSRF vulnerabilities.
import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface'
import { getCredentialData, getCredentialParam, parseJsonBody } from '../../../src/utils'
import { checkDenyList } from '../../../src/httpSecurity'| const credentialData = await getCredentialData(nodeData.credential ?? '', options ?? {}) | ||
| const apiKey = getCredentialParam('asqavApiKey', credentialData, nodeData) |
There was a problem hiding this comment.
Validate that the apiKey is present before proceeding. If it is missing, throw an error early to provide a clear and helpful error message to the user.
const credentialData = await getCredentialData(nodeData.credential ?? '', options ?? {})
const apiKey = getCredentialParam('asqavApiKey', credentialData, nodeData)
if (!apiKey) {
throw new Error('Asqav Sign Action: API Key is required. Please configure the Asqav API credential.')
}References
- When a feature requires a specific configuration (e.g., an API key), it is preferable to throw an error if the configuration is missing rather than silently falling back to a different implementation.
| try { | ||
| context = JSON.parse(trimmed) | ||
| } catch { | ||
| throw new Error('Asqav Sign Action: "Context" must be valid JSON.') | ||
| } |
There was a problem hiding this comment.
Use parseJsonBody instead of JSON.parse. parseJsonBody is a robust utility in Flowise that handles common JSON formatting issues such as trailing commas, single quotes, and comments, providing a much better user experience.
try {
context = parseJsonBody(trimmed)
} catch {
throw new Error('Asqav Sign Action: "Context" must be valid JSON.')
}| const agentResponse = await fetch(`${baseUrl}/agents/create`, { | ||
| method: 'POST', | ||
| headers, | ||
| body: JSON.stringify({ | ||
| name: 'flowise', | ||
| algorithm: 'ml-dsa-65', | ||
| capabilities: [] | ||
| }) | ||
| }) | ||
| if (!agentResponse.ok) { | ||
| const detail = await agentResponse.text().catch(() => '') | ||
| throw new Error( | ||
| `Asqav Sign Action: agent create failed (${agentResponse.status} ${agentResponse.statusText})${detail ? `: ${detail}` : ''}` | ||
| ) | ||
| } | ||
| const agent = (await agentResponse.json()) as { agent_id: string } |
There was a problem hiding this comment.
Creating a new agent via /agents/create on every single execution of the tool is highly inefficient and will clutter the user's Asqav account with many ephemeral agents named 'flowise'. Consider adding an optional agentId input parameter. If provided, the tool can skip the agent creation step and directly call /agents/${agentId}/sign, which also reduces the number of API roundtrips from two to one.
This adds a new tool node for Asqav, a service that lets you sign AI agent actions with post-quantum cryptographic compliance receipts.
What it does
The node takes an action type and optional context, then calls the Asqav API to produce a signed compliance receipt. It returns the signature ID, action ID, verification URL, timestamp, and signing algorithm. This is useful for audit trails on autonomous agent decisions.
The node uses direct
fetchcalls to the Asqav REST API. It has no third-party SDK dependency, so there is nothing extra to install or bundle.Files
nodes/tools/AsqavSignAction/AsqavSignAction.ts- the tool nodenodes/tools/AsqavSignAction/asqav.svg- iconcredentials/AsqavApi.credential.ts- API key credential (usestype: 'password'per the credential security guide)Setup
Users create an Asqav account at asqav.com, generate an API key in the dashboard, and connect it through the new "Asqav API" credential. No other configuration is needed.