This TypeScript library integrates a repository with the MaaS platform. It does not validate that a repository is safe, correct, or buildable. You are responsible for reviewing your configuration and build outputs. I am not a TypeScript developer and did my best; this is a quick V1 and the API/structure may evolve at any time. Don't take this as the final reference.
MalInt is a TypeScript library that connects a MaaS repository to an automation forge like Forgejo. It reads repository configuration files, loads client and state schemas, generates server and malware configurations, and dispatches build workflows. It also provides helpers to download build artifacts and to classify server variables as secrets or plaintext.
Integration logic is easy to duplicate and hard to keep consistent across projects. MalInt centralizes that logic so you can:
If you want to integrate a repository with the platform, follow the steps below.
You only need pnpm.
Install the library from Git
pnpm add git+https://github.com/Malware-as-a-Service/MalInt.git
Here is a small script that fetches configurations and triggers a build:
import { MalInt, ForgeKind } from "MalInt";
import type { Repository } from "MalInt/repositories";
const repository: Repository = {
baseAddress: "https://forgejo.example/",
ownerUsername: "Malware-as-a-Service",
name: "SayWare",
buildingBranch: "main",
configurationPath: "repository.toml",
token: "YOUR_FORGE_TOKEN",
};
const malIntResult = await MalInt.createMalInt(repository, ForgeKind.Forgejo);
if (malIntResult.isErr()) {
throw malIntResult.error;
}
const malInt = malIntResult.value;
// Generate the server configuration first if malware configuration references
// server values. Otherwise, you will get undefined reference errors.
// You can also fetch generated secrets or plaintext variables for your server
// environment, using the dedicated helper methods.
const serverConfigurationResult = await malInt.generateServerConfiguration();
if (serverConfigurationResult.isErr()) {
throw serverConfigurationResult.error;
}
// Set the server hostname after provisioning the server (ECS, VM, or similar).
// The malware needs to know the server hostname, so we generate the server
// configuration first and keep references from malware to server.
const hostnameResult = malInt.setServerHostname("c2.example.com");
if (hostnameResult.isErr()) {
throw hostnameResult.error;
}
const malwareConfigurationResult = await malInt.generateMalwareConfiguration();
if (malwareConfigurationResult.isErr()) {
throw malwareConfigurationResult.error;
}
// If your registry does not have the server image, build it before deployment
// so the hosting platform knows where to pull it from.
const buildResult = await malInt.buildMalware(malwareConfigurationResult.value);
if (buildResult.isErr()) {
throw buildResult.error;
}
const runIdentifier = buildResult.value;
// Poll at a regular interval until the build completes.
const artifactResult = await malInt.waitForMalware(runIdentifier);
if (artifactResult.isErr()) {
throw artifactResult.error;
}
// This is usually a zip buffer.
const malwareBuffer = artifactResult.value;
Contributions are what make the open source community such an amazing place to
learn, inspire, and create.
Any contributions you make are greatly appreciated.
If you want, you can help me with any kind of work, for example:
Distributed under the GPL 3.0 or later license.