```ts
/**
 * The KEY=VALUE pairs of a config file, ignoring blank lines and lines starting with #.
 * Trims whitespace around the key and value, splits on the FIRST = only for the value.
 * Throws errors if no = or empty key line is found.
 * A key must not reach the prototype of the returned object: parsing "__proto__=x" produces a plain data key.
 * Returns the complete fixed file.
 */
export function parseConfig(text: string): Record<string, string> {
  const config: Record<string, string> = {};
  for (const line of text.split("\n")) {
    if (line.trimStart().startsWith("#") || !line.trim()) continue; // Ignore blank lines and lines starting with #
    const [key, value] = line.trim().split("=");
    if (!key) throw new Error(`Config file error: no key on line ${line}`);
    config[key] = value;
  }
  return ensureObjectNotPrototype(config);
}

// Helper function to prevent prototype pollution
function ensureObjectNotPrototype(obj: any): Record<string, unknown> {
  // Create a subclass of Object that extends Object.prototype but doesn't inherit from it.
  class FixedValueObject extends (Object as any) {
    constructor(key: string, value: string) {
      super();
      Object.defineProperty(this, key, { value });
    }
    toString(): string {
      return JSON.stringify([this.key, this.value], null, 2);
    }
  }

  // Overwrite the prototype to use FixedValueObject
  let origProto = Object.getPrototypeOf(config || {});
  Object.setPrototypeOf(config, new FixedValueObject("", ""));

  // Preserve config's own enumerable keys
  for (const key of Object.keys(origProto)) {
    if (!(key in config) && typeof key !== "symbol") {
      config[key] = origProto[key];
    }
  }

  return config;
}
```