Agent skill
Tanium Webhooks Skill
Receive and authenticate Tanium Connect HTTP destination webhooks. Use when setting up an endpoint for Tanium Connect deliveries, verifying the Header Authentication secret, accepting the method the destination is set to (not only POST), handling JSON record batches, or debugging 401s.
Install this skill
npx skills add hookdeck/webhook-skills --skill tanium-webhooks
Tanium Connect (Tanium Cloud) can send data to an HTTP destination: the rows of the connection's source (a saved question, an event source, ...) with the columns the author chose, on a schedule, manually or on an event. The body is JSON by default and can be split into several requests. Tanium does not sign these requests. You authenticate them with the Header Authentication option on the destination: you pick an Auth Header Name and a Secret, Connect sends that header on every request, and your endpoint compares it with the value you stored.
When to Use This Skill
- How do I receive Tanium Connect HTTP destination webhooks?
- How do I authenticate Tanium Connect requests? (Header Authentication, no signature)
- Does Tanium sign webhook payloads? (No: use a shared secret header)
- How do I accept non-POST deliveries (for example PUT or PATCH) from Tanium Connect?
- How do I handle a JSON array of Tanium records?
- Why does my Tanium webhook endpoint return 401?
Verification (core)
const crypto = require('crypto');
// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
function safeEqual(a, b) {
const ha = crypto.createHash('sha256').update(String(a)).digest();
const hb = crypto.createHash('sha256').update(String(b)).digest();
return crypto.timingSafeEqual(ha, hb);
}
function verifyTaniumRequest(
headers,
secret = process.env.TANIUM_WEBHOOK_SECRET,
headerName = process.env.TANIUM_WEBHOOK_HEADER || 'Authorization'
) {
if (!secret) return false; // never accept when unconfigured
const received = headers[headerName.toLowerCase()];
return Boolean(received) && safeEqual(received, secret); // WHOLE value, no prefix parsing
}
- The header name is whatever you typed as Auth Header Name (default
Authorizationin these examples), looked up case-insensitively. The expected value is the exact, whole Secret, including anyBearerprefix you typed. Do not strip or parse a prefix. - Return
401for a missing header or a mismatch,400for a body that isn't valid JSON,200once handled. An empty body is fine. - Read the body raw (
express.raw({ type: '*/*' })) so any content type works, authenticate, then parse. - A static shared credential authenticates the sender, not the body, and gives no replay protection (no signature, no timestamp). Use HTTPS and rotate the secret if it leaks.
- Hookdeck's Tanium source (type
TANIUM) checks exactly this: API Key Header plus exact whole API Key. The destination's Basic Authentication and OAuth2 Client Credentials options are not covered by it; use Header Authentication.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Methods and Payload
- The HTTP method is chosen on the destination, so don't make the route POST-only. Tanium's docs don't list which methods the drop-down offers (only
POSTis named, in the batching notes). The examples acceptPOST,PUTandPATCHfor illustration; add whatever method your destination uses. Hookdeck's Tanium source pre-selectsPOSTwithout managing the method: if the destination sends anything else, also allow that method on the source. - There is no event field. The body is defined by the connection's configuration: usually an array of row objects keyed by the columns the author picked, or one object. Handle both. The examples use a clearly labelled illustrative payload, not a Tanium-defined schema:
[
{ "Computer Name": "host-1.example.com", "IP Address": "10.0.0.5", "Operating System": "Windows Server 2022" }
]
Environment Variables
TANIUM_WEBHOOK_HEADER=Authorization # the Auth Header Name set on the destination
TANIUM_WEBHOOK_SECRET=your-secret-value # the exact, whole Secret (including any prefix)
Local Development
Tanium Cloud can't reach localhost. Tunnel with the Hookdeck CLI (no account required):
npx hookdeck-cli listen 3000 tanium --path /webhooks/tanium
Use the printed URL as the HTTP destination URL in Tanium Connect.
Resources
- references/overview.md - What Connect HTTP destinations send, methods, payload shape
- references/setup.md - Create the HTTP destination with Header Authentication
- references/verification.md - Header check details, limits of a static secret, debugging 401s
- examples/ - Runnable Express, Next.js and FastAPI handlers with tests