diff --git a/lib/command.ts b/lib/command.ts
index 8fc166fb..ab0d5661 100644
--- a/lib/command.ts
+++ b/lib/command.ts
@@ -427,7 +427,20 @@ Command.setReplyTransformer("hgetall", function (result) {
   if (Array.isArray(result)) {
     const obj = {};
     for (let i = 0; i < result.length; i += 2) {
-      obj[result[i]] = result[i + 1];
+      const key = result[i];
+      const value = result[i + 1];
+      if (obj[key]) {
+        // can only be truthy if the property is special somehow, like '__proto__' or 'constructor'
+        // https://github.com/luin/ioredis/issues/1267
+        Object.defineProperty(obj, key, {
+          value,
+          configurable: true,
+          enumerable: true,
+          writable: true,
+        });
+      } else {
+        obj[key] = value;
+      }
     }
     return obj;
   }
diff --git a/test/functional/hgetall.ts b/test/functional/hgetall.ts
new file mode 100644
index 00000000..f4a38d8d
--- /dev/null
+++ b/test/functional/hgetall.ts
@@ -0,0 +1,12 @@
+import Redis from "../../lib/redis";
+import { expect } from "chai";
+
+describe("hgetall", function () {
+  it("should handle __proto__", async function () {
+    const redis = new Redis();
+    await redis.hset("test_key", "__proto__", "hello");
+    const ret = await redis.hgetall("test_key");
+    expect(ret.__proto__).to.eql("hello");
+    expect(Object.keys(ret)).to.eql(["__proto__"]);
+  });
+});