API Security

CSRF token

As a countermeasure to prevent Cross-Site Request Forgeries (CSRF), the Ardexa API requires a CSRF token be submitted with any request that modifies data, e.g. POST.

Two cookies are provided by the API for any request: connect.sid and XSRF-TOKEN. The CSRF token, XSRF-TOKEN, must be passed as an HTTP header, X-XSRF-TOKEN, for any POST, PUT or DELETE operation.


Here are three examples of fetching and using a CSRF token in Linux shell, Javascript and Python. All three are command line tool that read the TOKEN from the environment and take two arguments: the workgroup ID and the name of the new device, e.g.

./ 123123123 "test sh"
node create.mjs 123123123 "test js"
python3 123123123 "test py"

Linux shell


# $TOKEN is imported from the environment, it is the API token
arch="Linux 64 bit (x86_64)"

# Needs an XSRF token to use POST
xsrf_token=$(curl -s --cookie-jar /tmp/ardexa-cookie.txt -i https://$ardexa_cloud/api/v1/version | grep '^set-cookie: XSRF-TOKEN' | sed -e 's/.*TOKEN=\([^;]*\).*/\1/' -e 's/%2f/\//gi' -e 's/%2b/+/gi' -e 's/%3d/=/gi')

# Create the agent
curl -s -H "X-XSRF-TOKEN: $xsrf_token" -H "authorization: Bearer $TOKEN" -H "content-type: application/json" --cookie /tmp/ardexa-cookie.txt -X POST --output /tmp/ "https://$ardexa_cloud/api/v1/devices/$workgroup_id" -d "{\"name\": \"$device_name\", \"arch\": \"$arch\"}"

echo "Agent zip file can be found at /tmp/"


import { writeFileSync } from 'node:fs';
import got from 'got';
import {CookieJar} from 'tough-cookie';

const ardexaCloud = ''
const arch = 'Linux 64 bit (x86_64)'
const workgroupId = process.argv[2]
const deviceName = process.argv[3]

function getXsrf (cookieJar) {
  const cookies = cookieJar.getCookiesSync(`https://${ardexaCloud}`)
  for (const cookie of cookies) {
    if (cookie.key === 'XSRF-TOKEN') return decodeURIComponent(cookie.value)
  throw new Error('Failed to find XSRF token')

async function main () {
  const cookieJar = new CookieJar();
  const client =  got.extend({ cookieJar });
  await client.get(`https://${ardexaCloud}/api/v1/version`);
  const xsrf = getXsrf(cookieJar)
  const res = await`https://${ardexaCloud}/api/v1/devices/${workgroupId}`, {
    headers: {
      'X-XSRF-TOKEN': xsrf,
      authorization: `bearer ${process.env.TOKEN}`
    json: {
      name: deviceName,
  writeFileSync('/tmp/', res.rawBody)
  console.log('Agent zip file can be found at /tmp/')



import sys
import os
import requests

ardexa_cloud = ''
arch = 'Linux 64 bit (x86_64)'
workgroup_id = sys.argv[1]
device_name = sys.argv[2]

s = requests.Session()
xsrf = requests.utils.unquote(s.cookies.get_dict().get('XSRF-TOKEN'))
headers = {
  'X-XSRF-TOKEN': xsrf,
  'authorization': f'bearer {os.environ["TOKEN"]}'
json = {
    'name': device_name,
    'arch': arch
r ='https://{ardexa_cloud}/api/v1/devices/{workgroup_id}', headers=headers, json=json)
with open('/tmp/', 'wb') as f:

print('Agent zip file can be found at /tmp/')

Last updated