← Developers
Level 1: code Framework

TypeScript: LangChain.js and LangGraph.js

Node resolves through the system resolver by default, so Level 0 applies without changes. This page adds the guard and a tool that uses it.

Configuration and reference code for TypeScript: LangChain.js and LangGraph.js

The guard

The guard compares the answer against the block page address.

securdGuard.ts
// securdGuard.ts
// Held and blocked names resolve to the policy's block page address.
// Put that address (from the console, Sites > your site) in SECURD_BLOCK_ADDRS.
import { promises as dns } from "node:dns";

const BLOCK_ADDRS = new Set((process.env.SECURD_BLOCK_ADDRS ?? "").split(",").filter(Boolean));

export class SecurdHeld extends Error {
  constructor(public host: string, public agentRole: string) {
    super(`${host} is held or blocked for ${agentRole}`);
  }
}

export async function securdGuard(host: string, agentRole: string): Promise<void> {
  let answers: string[];
  try {
    answers = (await dns.lookup(host, { all: true })).map((a) => a.address);
  } catch {
    console.warn(JSON.stringify({ event: "securd.unresolved", agentRole, host }));
    throw new SecurdHeld(host, agentRole);
  }
  if (answers.some((a) => BLOCK_ADDRS.has(a))) {
    console.warn(JSON.stringify({ event: "securd.held", agentRole, host }));
    throw new SecurdHeld(host, agentRole);
  }
}

A guarded tool

tools.ts
import { DynamicTool } from "@langchain/core/tools";
import { securdGuard, SecurdHeld } from "./securdGuard";

const AGENT_ROLE = "docs-agent";

export const fetchPage = new DynamicTool({
  name: "fetch_page",
  description: "Fetch a page this agent is approved to read.",
  func: async (url: string) => {
    const host = new URL(url).hostname;
    try {
      await securdGuard(host, AGENT_ROLE);
    } catch (e) {
      if (e instanceof SecurdHeld) return `BLOCKED: ${e.message}`;
      throw e;
    }
    const res = await fetch(url);
    return (await res.text()).slice(0, 8000);
  },
});

Evaluate Agent DNS with your own agent traffic

Deploy on a single policy in learning mode and review the recorded destinations with your team.